当case when then else end 语句遇上sum或count等统计函数

事情是因为这样了——我需要按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语句哦。比如需要在一条记录里「同时统计出总人数,男生人数和女生人数~~~

猜你喜欢

转载自raising.iteye.com/blog/2280269