2013-01-07 20 views
2

我在这里找到了一个很好的资源( Comparing two bitmasks in SQL to see if any of the bits match ),用于在SQL数据库中执行搜索,在这里您使用位掩码存储具有多个属性的数据。在这个例子中,所有的数据都是以int形式存储的,where子句似乎只能用ints。在SQL中使用位串(而不是整数)匹配位掩码

有没有简单的方法来转换一个非常相似的测试用例来使用完整的位串呢?因此,而不是像一个例子:

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 

我可以来回转换,但它更容易与实际位串形象化。对于我的简单转换(上面),我得到一个错误,即运算符不能用于位串。有没有另外一种方法来设置这个工作?

+1

'SQL'是结构化查询语言的总称。你使用的是什么DBMS?字符串和位运算符因DBMS而异。 –

+0

我正在使用Postgres – ten

回答

6

的一种方法是对表达的右侧只使用一个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 0bit(3)

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

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

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

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

+0

太棒了,我知道我错过了一些小事。感谢您的建议,尽管在这种情况下空间不是问题,因此增加可读性可能更重要。 – ten