计算 postgresql 位掩码中相同的位置位

问题描述

我正在尝试计算 postgresql 中多个位掩码的每个相同位置位,这是问题的一个示例:

假设我有三个位掩码(二进制),例如:

011011011100110
100011010100101
110110101010101

现在我想要做的是获取每个单独列中的总位数,将上述掩码视为三行多列。

例如第一列计数2,第二列计数2,第三列计数1 等等...

实际上,我的数据库中的每个位掩码总共有 30 位。我想在 Postgresql 中做到这一点。如果需要,我愿意进一步解释问题。

解决方法

您可以通过使用 get_bit 函数和几个连接来实现:

SELECT sum(bit) FILTER (WHERE i = 0)  AS count_0,sum(bit) FILTER (WHERE i = 1)  AS count_1,...
       sum(bit) FILTER (WHERE i = 29) AS count_29
FROM bits
   CROSS JOIN generate_series(0,29) AS i
   CROSS JOIN LATERAL get_bit(b,i) AS bit;

在我的示例中,带有位串的列是 b

,

您可以使用按位和&操作者和BIGINT算术只要你的位串包含63个比特或更少的:

# create table bmasks (mask bit(15));
CREATE TABLE

# insert into bmasks values ('011011011100110'),('100011010100101'),('110110101010101');
INSERT 0 3

# with masks as (
  select (2 ^ x)::bigint::bit(15) as mask,x as posn
    from generate_series(0,14) as gs(x)
)
select m.posn,m.mask,sum((b.mask & m.mask > 0::bit(15))::int) as set_bits
  from masks m
       cross join bmasks b
 group by m.posn,m.mask;

┌──────┬─────────────────┬──────────┐
│ posn │      mask       │ set_bits │
├──────┼─────────────────┼──────────┤
│    0 │ 000000000000001 │        2 │
│    1 │ 000000000000010 │        1 │
│    2 │ 000000000000100 │        3 │
│    3 │ 000000000001000 │        0 │
│    4 │ 000000000010000 │        1 │
│    5 │ 000000000100000 │        2 │
│    6 │ 000000001000000 │        2 │
│    7 │ 000000010000000 │        2 │
│    8 │ 000000100000000 │        1 │
│    9 │ 000001000000000 │        2 │
│   10 │ 000010000000000 │        3 │
│   11 │ 000100000000000 │        1 │
│   12 │ 001000000000000 │        1 │
│   13 │ 010000000000000 │        2 │
│   14 │ 100000000000000 │        2 │
└──────┴─────────────────┴──────────┘
(15 rows)