事情是因为这样了——我需要按2个维度来分组,求出按这2个维度分组的总数情况(count),但同时也需要在这2个维度下求出按不同条件得出的总数,这些不同条件下分别得出的总数相加的和即为不加上条件的情况下的总数。比如:
假设有一张tablename表格,数据结构如下:
字段: id A B condition2
SELECT
COUNT(1) cnt,
A,
B
FROM
tablename
WHERE 1 = 1
AND B LIKE '201602%'
GROUP BY A,
B
ORDER BY A,
B
这是从tablename表中取出一定条件下按A,B分组的总数情况,假设现在我B的条件不变,需要统计根据condition字段(假设condition是一个枚举值的字段,即它的取值为1,2,3三种可能)来变化的总数,那么我需要分别写几个sql:
SELECT
COUNT(1) cnt,
A,
B
FROM
tablename
WHERE 1 = 1
AND B LIKE '201602%'
AND condition = '1'
GROUP BY A,
B
ORDER BY A,
B
这里的count统计条件是AND condition = '1' 还有可能是AND condition = '2'和AND condition = '3',然后这些不同的condition取值条件下的count统计取值分别为cnt1 cnt2 cnt3 则cnt1 + cnt2 + cnt3 = cnt(不加上condition过滤条件时的统计值).
问题来了,如何在一条记录里同时把cnt和cnt1-cnt3都展示出来呢?
之前我是先求出cnt的集合,再循环每一条记录,根据每条记录的A,B和condition取值去得到该条记录加上condition后对应的cnt,但后来发现这是十分不可取的,因为每条记录都得连接数据库去执行sql查询,显得效率低下。。
后来发现在这种情形下,case when then else end就可以起作用,但十分神奇的是,他竟然也能够和count函数结合起来:
ELECT
COUNT(1) cnt,
COUNT(
CASE
WHEN condition = '1'
THEN 1
ELSE NULL
END
) cnt1,
COUNT(
CASE
WHEN condition = '2'
THEN 1
ELSE NULL
END
) cnt2,
COUNT(
CASE
WHEN condition = '3'
THEN 1
ELSE NULL
END
) cnt3,
A,
B
FROM
tablename
WHERE 1 = 1
AND B LIKE '201602%'
GROUP BY A,
B
ORDER BY A,
B
这里需要注意count函数里面包围case when then else end的用法;还有一点需注意的是:count(null)得到的是0,这表明不符合当前条件下,走的是else null 这时候count(null)就为0啦~~,即不在当前条件下统计,否则count(1)就是统计了!!!
很神奇吧!看看结果:
多仔细几条记录,会发现每条记录都同时包含了cnt 和cnt1-cnt3,并且cnt = cnt1 + cnt2 + cnt3. 这说明我们这句sql求出的记录是正确的!
补充,同理的还有sum函数包围case when then else end,需注意不满足当前条件走else分支时,是要这样写的,sum(case when condition='1' then val else 0 end),即sum(0)才是0.
小结下:sum(0) = 0 , count(null) = 0. 在遇到这种情形的统计时,可考虑case when then else end语句哦。比如需要在一条记录里「同时」统计出总人数,男生人数和女生人数~~~