我声明了以下标志:
0 - None
1 - Read
2 - Write
4 - View
我想编写一个查询,该查询将对此位掩码进行分组并获取所使用的每个标志的计数。
person mask
a 0
b 3
c 7
d 6
结果应为:
flag count
none 1
read 2
write 3
view 2
任何提示都将不胜感激。
对于Craig
SELECT lea.mask as trackerStatusMask,
count(*) as count
FROM Live le
INNER JOIN (
... --some guff
) lea on le.xId = lea.xId
WHERE le.xId = p_xId
GROUP BY lea.mask;
答案 0 :(得分:3)
select
count(mask = 0 or null) as "None",
count(mask & 1 > 0 or null) as "Read",
count(mask & 2 > 0 or null) as "Write",
count(mask & 4 > 0 or null) as "View"
from t
答案 1 :(得分:2)
以下是我接近它的方法:
-- (after fixing the idiotic mistakes in the first version)
SELECT
count(nullif(mask <> 0, True)) AS "none",
count(nullif(mask & 2,0)) AS "write",
count(nullif(mask & 1,0)) AS "read",
count(nullif(mask & 4,0)) AS "view"
FROM my_table;
-- ... though @ClodAldo's version of it below is considerably clearer, per comments.
这不会GROUP BY
这样做;相反,它扫描表并一次收集数据,产生面向列的结果。
如果您需要以行格式显示,可以使用crosstab
模块中的tablefunc
函数或手动来旋转结果。
GROUP BY
,请爆炸位掩码您不能以简单的方式使用GROUP BY
,因为它希望行只属于一个组。您的行显示在多个组中。如果必须使用GROUP BY
,则必须通过生成“爆炸”位掩码来执行此操作,其中一个输入行被复制以生成多个输出行。这可以通过9.3中的LATERAL
函数调用,或9.2中的SRF-in-SELECT,或者通过简单地对VALUES
子句进行连接来完成:
SELECT
CASE
WHEN mask_bit = 1 THEN 'read'
WHEN mask_bit = 2 THEN 'write'
WHEN mask_bit = 4 THEN 'view'
WHEN mask_bit IS NULL THEN 'none'
END AS "flag",
count(person) AS "count"
FROM t
LEFT OUTER JOIN (
VALUES (4),(2),(1)
) mask_bits(mask_bit)
ON (mask & mask_bit = mask_bit)
GROUP BY mask_bit;
我认为你不会有太多运气使得它像单个表扫描一样高效。