表名: 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來達到相同效果.