问题描述
我有一个表,用于存储用户为产品创建的帐户类型。有3种可能的路径。
- 他们可以创建一个试用帐户,然后创建一个完整帐户。
- 他们只能创建一个完整的帐户。
- 他们可以创建试用帐户。
在第一种情况下,将创建2个条目,而在其他情况下,将创建1个条目。下面的示例源表:
+------+--------------+
| user | account_type |
+------+--------------+
| 1 | trial |
+------+--------------+
| 1 | full |
+------+--------------+
| 2 | full |
+------+--------------+
| 3 | full |
+------+--------------+
| 4 | trial |
+------+--------------+
| 4 | full |
+------+--------------+
| 5 | trial |
+------+--------------+
| 5 | full |
+------+--------------+
| 6 | trial |
+------+--------------+
| 7 | full |
+------+--------------+
我想计算创建一个试用帐户然后再创建一个完整帐户的用户数量,以及直接创建一个完整帐户的用户数量。预计的下表如下:
+-------------------+------------------------+
| full_account_only | trial_and_full_account |
+-------------------+------------------------+
| 124 | 256 |
+-------------------+------------------------+
到目前为止,我的查询是:
select sum(case
when account_type_cnt = 1 then
1
end) as "full_account_only",sum(case
when account_type_cnt = 2 then
1
end) as "trial_and_full_account "
from (select user,count(distinct(account_type)) as account_type_cnt
from tbl
group by user)
,但我意识到,这将无法满足仅计算完整帐户的用户的计数标准。有人可以帮助解决这个问题吗?
解决方法
您可以使用两个级别的聚合。我会将计数放在单独的行中,如下所示:
select num_trial,num_full,count(*) as num_users
from (select user,sum(case when account_type = 'trial' then 1 else 0 end) as num_trial,sum(case when account_type = 'full' then 1 else 0 end) as num_full
from t
group by user
) u
group by num_trial,num_full;
您可以轻松地对此进行修改,以将值放在列中:
select sum(case when num_trial > 0 and num_full = 0 then 1 else 0 end) as only_trial,sum(case when num_full > 0 and num_trial = 0 then 1 else 0 end) as only_full,sum(case when num_full > 0 and num_trial > 0 then 1 else 0 end) as both
from (select user,num_full;
,
与Gordon类似的方法,但实现方式略有不同,部分是因为我更喜欢在计算事物时使用count,而不是求和。您可以将计数作为标志来获取每个用户存在的帐户类型:
select usr,count(case when account_type = 'trial' then account_type end) as trial_cnt,count(case when account_type = 'full' then account_type end) as full_cnt
from tbl
group by usr
USR | TRIAL_CNT | FULL_CNT
--: | --------: | -------:
6 | 1 | 0
2 | 0 | 1
4 | 1 | 1
3 | 0 | 1
5 | 1 | 1
7 | 0 | 1
1 | 1 | 1
,然后将其用作内部查询以及另一层条件聚合:
select
count(case when trial_cnt > 0 then usr end) as trial,count(case when full_cnt > 0 then usr end) as full,count(case when full_cnt > 0 and trial_cnt = 0 then usr end) as full_only,count(case when full_cnt > 0 and trial_cnt > 0 then usr end) as trial_and_full
from (
select usr,count(case when account_type = 'trial' then usr end) as trial_cnt,count(case when account_type = 'full' then usr end) as full_cnt
from tbl
group by usr
)
TRIAL | FULL | FULL_ONLY | TRIAL_AND_FULL
----: | ---: | --------: | -------------:
4 | 6 | 3 | 3