我有下表
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(特定摆脱和特定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所以我想返回为零)
答案 0 :(得分:1)
您需要的是一个包含您想要输出的所有值的驱动程序表。然后,您可以将外部连接到实际数据:
SELECT count(notification.eid) as count
FROM (select distinct eid
from notification
) drivers left outer join
(select *
from notification
WHERE rid = %d AND vs = %d AND isN = 1
) n
on driver.eid = notification.eid
GROUP BY driver.eId
您还应该在eid
子句中包含select
,除非您依赖于输出的最终排序(MySQL与其他任何数据库不同,确保在{{}之后对结果进行排序{1}}。)
答案 1 :(得分:1)
这是获取指定结果集的一种方法:
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,但在这种情况下,它足够简单以避免需要。)
请注意,这种“计数”方法的一个优点是它可以轻松扩展以获得“组合”计数,或者包含几个不同计数的行。 e.g。
, 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子句中执行这些检查,我们可能需要多次遍历表。
答案 2 :(得分:0)
所以,基本上你要找的是这个?...
SELECT rid,eid,vs, COUNT(*) FROM notification GROUP BY rid,eid,vs;
+-----+-----+----+----------+
| rid | eid | vs | COUNT(*) |
+-----+-----+----+----------+
| 0 | 22 | 2 | 2 |
| 3 | 21 | 2 | 1 |
| 3 | 22 | 2 | 2 |
| 60 | 21 | 2 | 6 |
| 60 | 22 | 2 | 3 |
| 81 | 21 | 2 | 1 |
| 81 | 22 | 2 | 3 |
+-----+-----+----+----------+
7 rows in set (0.11 sec)