表名: user_active_day (用户日活表)

表内容:

user_id(用户id)   user_is_new(是否新用户 1:新增用户 0:老用户) location_city(用户所在地区) partition_date(日期分区)

需求:

  找出20180901至今的xxx地区的用户日活量以及新增用户量

思路:

  筛选日期分区和地区,统计user_id的数量为用户日活量,统计user_is_new = 1的数量为新增用户量.

最开始写的hql语句

select partition_date,count(user_id),
count(if(user_is_new = 1, user_id, 0)) --注意新增用户量的统计
from dw.nice_live_dw_user_active_day
where location_city like '%xxx%' and partition_date >= 20180901
group by partition_date;

我们使用count(if())来进行筛选统计,但是效果并没有达到,出现的结果如下

20180901	16737  16737

根本就没有达到筛选的目的,为什么?

这就要从count的机制说起

首先count()是对数据进行计数,说白了就是你来一条数据我计数一条,我不关心你怎么分类,我只对数据计数

每条数据从if()函数出来,还是一条数据,所以count+1

所以count(user_id)跟count(if(user_id))没有任何的区别.

我们稍做修改

select partition_date,count(user_id),
count(distinct if(user_is_new = 1, user_id, 0)) --注意新增用户量的统计,加了distinct去重
from dw.nice_live_dw_user_active_day
where location_city like '%xxx%' and partition_date >= 20180901
group by partition_date;

结果如下

20180901	16737  261

这次看着就像是对了吧,我们加了distinct进行去重

每次来一条数据先过if()然后再进行去重最后统计.但是实际上结果依旧是错误的.

我们来模拟一下筛选统计的过程

我们有这样四条数据

user_id    user_is_new

1               1

2              0

3              1

4              0

表中的数据是一条一条遍历的,

(1)当user_id = 1的数据过来的时候,我们先过if函数  user_is_new = 1    ==>  count(distinct user_id = 1),

然后我们把user_id = 1进行重复判断,我们用一个模拟容器来模拟去重,

从容器里找user_id = 1的数据,发现没有,不重复,所以通过我们把count+1,然后把user_id = 1的数据放入,用于下条去重

(2)当user_id = 2的数据过来的时候,我们先过if函数  user_is_new = 0    ==>  count(distinct 0),

然后我们把0进行重复判断,

从容器里找0的数据,发现没有,不重复,所以通过我们把count+1,然后把0的数据放入,用于下条去重

(3)当user_id = 3的数据过来的时候,我们先过if函数  user_is_new = 1    ==>  count(distinct user_id = 3),

然后我们把user_id = 3进行重复判断,

从容器里找user_id = 3的数据,发现没有,不重复,所以通过我们把count+1,然后把user_id = 3的数据放入,用于下条去重

(4)当user_id = 4的数据过来的时候,我们先过if函数  user_is_new = 0    ==>  count(distinct 0),

然后我们把0进行重复判断,

从容器里找0的数据,发现重复,是之前user_id = 2的时候过if()转化成0的那条数据,所以count不执行

我们通过模拟count(distinct if)过程发现,在count的时候我们把不符合条件的最开始的那条语句也count进去了一次

导致最终结果比正确结果多了1.

我们在原基础语句上再减去1就是正确的hql语句

其实在日常中我们做分类筛选统计的时候一般是用sum来完成的,符合条件sum+1,不符合条件sum+0

select partition_date,count(user_id),
sum(if(user_is_new = 1, 1, 0)) --用sum进行筛选统计
from dw.nice_live_dw_user_active_day
where location_city like '%xxx%' and partition_date >= 20180901
group by partition_date;

结果如下

20180901	16737  260

sum(if)只试用于单个条件判断,如果筛选条件很多,我们可以用sum(case when then else end)来进行多条件筛选

注意,hive中并没有sum(distinct col1)这种使用方式,我们可以使用sum(col) group by col来达到相同效果.

【hive】count() count(if) count(distinct if) sum(if)的区别的更多相关文章

  1. 【MySQL】汇总数据 - avg()、count()、max()、min()、sum()函数的使用

    第12章 汇总数据 文章目录 第12章 汇总数据 1.聚集函数 1.1.AVG()函数 avg() 1.2.COUNT()函数 count() 1.3. MAX()函数 max() 1.4.MIN() ...

  2. [MongoDB]count,gourp,distinct

    摘要 上篇文章介绍了CRUD的操作,会了这些,基本上可以完成很多工作了.但如果遇到统计类的操作,那么就需要学习下本篇的内容了. 相关文章 [MongoDB]入门操作 [MongoDB]增删改查 cou ...

  3. 【优化】COUNT(1)、COUNT(*)、COUNT(常量)、COUNT(主键)、COUNT(ROWID)、COUNT(非空列)、COUNT(允许为空列)、COUNT(DISTINCT 列名)

    [优化]COUNT(1).COUNT(*).COUNT(常量).COUNT(主键).COUNT(ROWID).COUNT(非空列).COUNT(允许为空列).COUNT(DISTINCT 列名) 1. ...

  4. Django学习路17_聚合函数(Avg平均值,Count数量,Max最大,Min最小,Sum求和)基本使用

    使用方法: 类名.objects.aggregate(聚合函数名('表的列名')) 聚合函数名: Avg 平均值 Count数量 Max 最大 Min 最小 Sum 求和 示例: Student.ob ...

  5. Oracle 中count(1) 和count(*) 的区别

    count()与count(*)比较: 如果你的数据表没有主键,那么count()比count(*)快 如果有主键的话,那主键(联合主键)作为count的条件也比count(*)要快 如果你的表只有一 ...

  6. 【MySQL】技巧 之 count(*)、count(1)、count(col)

    只看结果的话,Select Count(*) 和 Select Count(1) 两着返回结果是一样的. 假如表沒有主键(Primary key), 那么count(1)比count(*)快,如果有主 ...

  7. 关于count(1) 和 count(*)

    Q:What is the difference between count(1) and count(*) in a sql queryeg.select count(1) from emp; an ...

  8. select count(*)和select count(1)的区别 (转)

    A 一般情况下,Select Count (*)和Select Count(1)两着返回结果是一样的 假如表沒有主键(Primary key), 那么count(1)比count(*)快, 如果有主键 ...

  9. 【转载】Oracle 中count(1) 、count(*) 和count(列名) 函数的区别

    1)count(1)与count(*)比较: 1.如果你的数据表没有主键,那么count(1)比count(*)快2.如果有主键的话,那主键(联合主键)作为count的条件也比count(*)要快3. ...

随机推荐

  1. linux内核cdev_init系列函数(字符设备的注册)

    内核中每个字符设备都对应一个 cdev 结构的变量,下面是它的定义: linux-2.6.22/include/linux/cdev.h struct cdev {    struct kobject ...

  2. [原创]chromium源码阅读-进程间通信IPC.消息的接收与应答

    chromium源码阅读-进程间通信IPC.消息的接收与应答   chromium源码阅读-进程间通信IPC.消息的接收与应答 介绍 chromium进程间通信在win32下是通过命名管道的方式实现的 ...

  3. js-template-art【一】简述

    一.官方地址 地址:https://github.com/aui/art-template 二.概述 官方对比 三.特性 拥有接近 JavaScript 渲染极限的的性能 调试友好:语法.运行时错误日 ...

  4. spring requestmapping 拦截多个请求

    @RequestMapping(value = {"/picture_content/{id}","/attachment_content/{id}",&quo ...

  5. Java用数据结构解决实现问题之数学问题

    有趣的整数: 完数:如果一个数字恰好等于他的因子之和,就叫做完数,需求是求出10000以内的所有的完数. 解法:1.用n去除以1-n之间的所有的整数,将能整除的被除数保存到一个数组中,作为n的一个因子 ...

  6. A Practical Guide to Support Vector Classi cation

    <A Practical Guide to Support Vector Classication>是一篇libSVM使用入门教程以及一些实用技巧. 1. Basic Kernels: ( ...

  7. hdu 5140 主席树

    这题说的是每个员工有工资 水平 在公司待的年限这几个属性,有大量的查询 查的是在一定的水平和工作年限的工人总工资是多少 这个思路是比较简单的我们按照他们的水平排序,排完后,使用主席树不断地往里面插,然 ...

  8. Java Character 类

    Character 类用于对单个字符进行操作. Character 类在对象中包装一个基本类型 char 的值 实例 char ch = 'a'; // Unicode 字符表示形式 char uni ...

  9. 服务器环境配置nginx / php / php-fpm(一)

    登陆,升级应用,查询和关闭selinux yum update getenforce setenforce 0 vi /etc/selinux 添加非root用户 adduser deploy pas ...

  10. MySQL事务之-2

    在上一篇中我们提到了MySQL的事务特性,这一片主要讲述事务的实现. 事务的隔离性由锁来实现.原子性,一致性,持久性通过数据库的redo和undo log来实现. redo恢复提交事务修改页的操作,而 ...