最简单的旋转结果
这是我的处理方法:
-- (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
,则必须通过生成“爆炸”位掩码来执行此操作,其中一个输入行被复制以产生多个输出行。这可以通过LATERAL
9.3 中的函数调用或 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;
不过,我不认为你会很幸运地让它像单表扫描一样高效。