【问题标题】:Postgres bitmask group byPostgres 位掩码分组方式
【发布时间】:2013-08-01 01:06:34
【问题描述】:

我声明了以下标志:

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

任何提示将不胜感激。

给克雷格

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;

【问题讨论】:

  • 你在其他查询中如何使用这个掩码? 你已经尝试过什么?
  • @CraigRinger,我有分组依据,所以我可以对掩码和计数进行分组,我只是不知道如何将掩码拆分为由它组成的标志。
  • 好的,请显示您已有的部分查询。

标签: postgresql bit-manipulation postgresql-9.2 bitmask


【解决方案1】:

SQL Fiddle

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

【讨论】:

  • 我无法决定是否喜欢您使用or null。它是标准的,与 nullif 相比很好,但对于不熟悉 SQL 的人来说,阅读起来就不太清楚了。
  • @Craig 你知道吗?我精通 SQL,每当我看到 nullif 函数时,我必须努力记住它是如何工作的,而真值表已准备好在我的脑海中使用,嗯......,不是所有的日子,但至少在美好的日子 :) 我的nullif 问题非常严重,以至于我不得不测试您的第一个查询以确保它是错误的,我很抱歉地说它是错误的。
  • 是吗? sqlfiddle.com/#!12/8bed0/7 。呵呵,也是。教我不要测试东西,它包含两个明显和愚蠢的错误。
  • 在“无”的情况下还有一个更严重的愚蠢错误......该死。
【解决方案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;相反,它会扫描表并一次性收集数据,生成面向列的结果。

如果您需要以行形式显示,您可以使用 tablefunc 模块中的 crosstab 函数或手动旋转结果。

如果你真的非要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;

不过,我认为你不会像单表扫描那样高效。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2012-02-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-04-28
    相关资源
    最近更新 更多