我有下表

id  rid     eId     vs  isN
24  3   22  2   1
25  3   21  2   1
26  60  21  2   1
27  60  21  2   1
28  60  21  2   1
29  60  21  2   1
30  60  21  2   1
31  60  21  2   1
32  81  21  2   1
35  60  22  2   1
36  81  22  2   1
37  0   22  2   1
38  60  22  2   1
39  81  22  2   1
40  0   22  2   1
41  60  22  2   1
42  81  22  2   1
43  3   22  2   1


eId上,我有8个不同的数字
我想计算这八个不同的eid,甚至算作“ 0”,我想要得到的是一个包含8个值的数组,并且键应该是八个不同的名称。每次我计数时,“ vs”是3个不同的数字
我想要在“ rid” =%d和“ vs” =%d(特定rid和特定vs)上进行操作

SELECT count(*) as count FROM notification
WHERE rid = 60 AND vs = 2 AND isN = 1 GROUP BY eId

rid=>60,21=>6,22=>3,vs=>2,isN=>1


(这就是我从上面得到的)

rid=>60,21=>6,22=>3,23=>0,33=>0,34=>0,35=>0,36=>0,41=>0,42=>0,vs=>2,isN=>1


(这就是我想要的。八个数,当然这个数字不算在eId上,所以我想返回零)

最佳答案

这是获取指定结果集的一种方法:

 SELECT d.rid           AS `rid`
      , SUM(n.eid<=>21) AS `21`
      , SUM(n.eid<=>22) AS `22`
      , SUM(n.eid<=>23) AS `23`
      , SUM(n.eid<=>33) AS `33`
      , SUM(n.eid<=>34) AS `34`
      , SUM(n.eid<=>35) AS `35`
      , SUM(n.eid<=>36) AS `36`
      , SUM(n.eid<=>41) AS `41`
      , SUM(n.eid<=>42) AS `42`
      , d.vs            AS `vs`
      , d.isN           AS `isN`
   FROM ( SELECT %d AS rid, %d AS vs, 1 AS isN ) d
   LEFT
   JOIN notification n
     ON n.rid = d.rid
    AND n.vs  = d.vs
    AND n.isN = d.isN
  GROUP
     BY d.rid
      , d.vs
      , d.isN


注意:表达式(n.eid<=>21)IF(n.eid=21,1,0)的缩写,或更符合ANSI标准的CASE WHEN n.eid = 21 THEN 1 ELSE 0 END。给出0或1,然后可以使用SUM函数进行汇总。

使用以下任何一种形式,您都可以获得等效的结果:

     , SUM(n.eid<=>21)                             AS `21`
     , COUNT(IF(n.eid=22,1,NULL))                  AS `22`
     , SUM(IF(n.eid=23,1,0))                       AS `23`
     , COUNT(CASE WHEN n.eid = 33 THEN 1 END)      AS `33`
     , SUM(CASE WHEN n.eid = 34 THEN 1 ELSE 0 END) AS `34`




我们在这里使用的“技巧”是确保我们将别名为d的内联视图返回一行。然后,我们使用LEFT JOIN运算符从notification表中拾取所有“匹配”的行。 GROUP BY将强制将所有这些行折叠(汇总)回到单个行。我们在每一行上使用条件测试来查看是否将其包含在给定的计数中,“窍门”是为每一行返回0或1,然后将所有0与1s获得计数。

注意:如果您使用COUNT(expr)聚合,您希望该expr在行要包括在计数中时返回非NULL,而在行不包括在计数中时返回NULL。

如果使用SUM(expr),则希望expr在要将行包括在计数中时返回1,在没有计数时返回0。 (我们希望使用0而不是NULL,以便在没有要包含的行的情况下保证SUM(expr)将返回“零计数”(即0而不是NULL)。(当然,我们可以使用IFNULL函数将NULL替换为0,但是在这种情况下,它很简单,就可以避免这样做。)



请注意,这种“计数”方法的优点是可以轻松扩展以获取“组合”计数,或在多个不同计数中包含一行。例如

    , SUM(IF(n.eid IN (41,42),1,0)) AS `total_41_and_42`


将使我们的总数eid = 41和eid = 42行。 (这不是一个很好的例子,因为我们可以通过将两个计数加在一起在客户端轻松地计算出来。但是,如果您要进行更复杂的计数,并且想要将多个计数为单个行,则这确实是一个优势。列 ...

   , SUM(IF(n.eid=42,1,0))            AS eid_42
   , SUM(IF(n.eid=42 AND foo=1,1,0)   AS eid_42_foo_1
   , SUM(IF(n.eid=42 AND foo=2,1,0))  AS eid_42_foo_2


我们只需通过notification表一次即可获得所有这些单独的计数。如果我们尝试在WHERE子句中进行这些检查,则可能需要多次通过该表。

关于mysql - 每个不存在值的GROUP BY COUNT个,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/14816402/

10-13 07:14