我有下表
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/