【问题标题】:Matching bitmasks using bitstrings (instead of ints) in SQL在 SQL 中使用位串(而不是整数)匹配位掩码
【发布时间】:2013-01-08 05:39:30
【问题描述】:

我在这里找到了一个很好的资源( Comparing two bitmasks in SQL to see if any of the bits match ) 用于在 SQL 数据库中进行搜索,您在其中使用位掩码存储具有多个属性的数据。但是,在示例中,所有数据都存储为整数,而 where 子句似乎只适用于整数。

有没有一种简单的方法可以将非常相似的测试用例转换为使用完整的位串?所以而不是像这样的例子:

with test (id, username, roles)
AS
(
    SELECT 1,'Dave',1
    UNION SELECT 2,'Charlie',3
    UNION SELECT 3,'Susan',5
    UNION SELECT 4,'Nick',2
)
select * from test where (roles & 7) != 0 

而不是类似:

with test (id, username, roles)
AS
(
    SELECT 1,'Dave',B'001'
    UNION SELECT 2,'Charlie',B'011'
    UNION SELECT 3,'Susan',B'101'
    UNION SELECT 4,'Nick',B'110'
)
select * from test where (roles & B'001') != 0 

我可以来回转换,但使用实际的位串更容易可视化。对于我的简单转换(上图),我收到一个错误,即运算符不适用于位串。还有其他可行的设置方法吗?

【问题讨论】:

  • SQL 是结构化查询语言的通用术语。您使用的是什么 DBMS?字符串和位运算符因 DBMS 而异。

标签: sql postgresql match bitmask bitstring


【解决方案1】:

一种方法是在表达式右侧也使用bit string

WITH test (id, username, roles) AS (
   VALUES
     (1,'Dave',B'001')
    ,(2,'Charlie',B'011')
    ,(3,'Susan',B'101')
    ,(4,'Nick',B'110')
   )
SELECT *, (roles & B'001') AS intersection
FROM   test
WHERE  (roles & B'001') <> B'000';

或者您可以将integer 0 转换为bit(3)

...
WHERE  (roles & B'001') <> 0::bit(3);

您可能对此相关答案感兴趣,该答案演示了在 booleanbit stringinteger 之间转换的多种方法:
Can I convert a bunch of boolean columns to a single bitmap in PostgreSQL?

请注意,将数据存储为integer 可以节省一些空间。 integer 需要 4 字节 最多 32 位信息,而 - 我引用 manual at said location:

位串值每组 8 位需要 1 个字节加 5 或 8 字节开销取决于字符串的长度 [...]

【讨论】:

  • 太棒了,我知道我错过了一些小东西。感谢您的提示,尽管在这种情况下空间不是问题,因此提高易读性可能更重要。
猜你喜欢
  • 1970-01-01
  • 2010-09-13
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-03-09
  • 2021-08-27
  • 2012-05-16
相关资源
最近更新 更多