比较SQL中的两个位掩码以查看是否有任何位匹配

比较SQL中的两个位掩码以查看是否有任何位匹配,sql,sql-server,tsql,bitmask,Sql,Sql Server,Tsql,Bitmask,是否有一种方法可以比较Transact-SQL中的两个位掩码以查看是否有任何位匹配?我有一个用户表,其中包含用户所属的所有角色的位掩码,我想选择在提供的位掩码中具有任何角色的所有用户。因此,使用下面的数据,6个设计师+程序员的角色位掩码应该选择Dave、Charlie和Susan,而不是Nick User Table ---------- ID Username Roles 1 Dave 6 2 Charlie 2 3 Susan 4 4 Nick

是否有一种方法可以比较Transact-SQL中的两个位掩码以查看是否有任何位匹配?我有一个用户表,其中包含用户所属的所有角色的位掩码,我想选择在提供的位掩码中具有任何角色的所有用户。因此,使用下面的数据,6个设计师+程序员的角色位掩码应该选择Dave、Charlie和Susan,而不是Nick

User Table ---------- ID Username Roles 1 Dave 6 2 Charlie 2 3 Susan 4 4 Nick 1 Roles Table ----------- ID Role 1 Admin 2 Programmer 4 Designer
有什么想法吗?谢谢。

使用Transact-SQL&并将结果与零进行比较。更好的是,不用将角色编码为整数列的位,而是使用布尔列,每个角色一个。然后,您的查询将简单地对设计师和程序员友好。如果您希望角色在应用程序的生命周期内发生很大变化,那么可以使用多对多表来映射用户与其角色之间的关联。这两种选择都比依赖于位AND运算符的存在更具可移植性。

要查找所有程序员,请使用:

SELECT * FROM UserTable WHERE Roles & 2 = 2

从mask1和mask2>0的表格中选择*示例:

DECLARE @Mask int
SET @Mask = 6

DECLARE @Users TABLE
(
ID int,
Username varchar(50),
Roles int
)

INSERT INTO @Users (ID, Username, Roles) 
SELECT 1, 'Dave', 6
UNION
SELECT 2, 'Charlie', 2
UNION
SELECT 3, 'Susan', 4
UNION
SELECT 4, 'Nick', 1

SELECT * FROM @Users WHERE Roles & @Mask > 0

您的问题的答案是使用按位&如下所示:

SELECT * FROM UserTable WHERE Roles & 6 != 0
        1   2   4
------------------
Dave    0   1   1
Charlie 0   1   0
Susan   0   0   1   
Nick    1   0   0
6可以交换为您想要检查任何用户是否有一个或多个位的位字段的任何组合。当试图验证这一点时,我通常发现用二进制直接写出这一点很有帮助。您的用户表如下所示:

SELECT * FROM UserTable WHERE Roles & 6 != 0
        1   2   4
------------------
Dave    0   1   1
Charlie 0   1   0
Susan   0   0   1   
Nick    1   0   0
你的测试6是这样的

        1   2   4
------------------
Test    0   1   1
如果我们对每个进行bitwaise测试的人进行检查,并对照测试,我们得到以下结果:

        1   2   4
------------------
Dave    0   1   1   
Test    0   1   1
Result  0   1   1 (6)

Charlie 0   1   0
Test    0   1   1
Result  0   1   0 (2)

Susan   0   0   1
Test    0   1   1
Result  0   0   1 (4)

Nick    1   0   0
Test    0   1   1
Result  0   0   0 (0) 
以上内容应证明结果不为零的任何记录都具有一个或多个请求的标志

编辑:这是您想要检查的测试用例

with test (id, username, roles)
AS
(
    SELECT 1,'Dave',6
    UNION SELECT 2,'Charlie',2
    UNION SELECT 3,'Susan',4
    UNION SELECT 4,'Nick',1
)
select * from test where (roles & 6) != 0  // returns dave, charlie & susan


&运算符用于将位掩码与一个角色进行比较,但不用于将位掩码与另一个位掩码进行比较。我想我必须使用动态sql,并将每个角色放入where子句中。@Nick-错-请参阅我的答案。OP正在查找程序员或设计人员这会产生错误的结果。试着用4-Susan和Dave都有4-但它只返回Susan。非常理想,谢谢。太久以前,我不记得我最终是如何绕过这个问题的,但这几乎肯定是一个更好的解决方案!
select * from test where (roles & 7) != 0 // returns dave, charlie, susan & nick