首页
学习
活动
专区
工具
TVP
发布
社区首页 >问答首页 >SQL Server逐位处理,如C#枚举标志

SQL Server逐位处理,如C#枚举标志
EN

Stack Overflow用户
提问于 2012-11-30 20:33:57
回答 5查看 19.2K关注 0票数 31

如何在SQL Server中使用标志的处理,例如在C#中的枚举上?

例如,如何返回属于列表或类似条件的用户列表:

代码语言:javascript
复制
ConditionAlpha = 2
ConditionBeta  = 4
ConditionGamma = 8

..。

那么就会有一些用户遇到这些情况,比如:

代码语言:javascript
复制
User1: 6 (conditions Alpha and Beta)
User2: 4 (condition Beta)
User3: 14 (conditions Alpha, Beta and Gamma)

..。

我们希望能够执行一个查询,其中我们说get all users with first condition Alpha,在这个场景中,它将返回用户1和3,即使他们还有其他条件。

EN

回答 5

Stack Overflow用户

发布于 2012-11-30 20:52:58

用于检查是否在SQL中设置了标志的位运算符为&WHERE子句需要计算为BOOLEAN表达式,如下所示:

代码语言:javascript
复制
create table #temp (id int, username varchar(20), flags int)

insert into #temp values
(1, 'User1', 6 /* (2 | 4) */),
(2, 'User2', 4),
(3, 'User3', 14 /* (2 | 4 | 8) */)

declare @ConditionOne int = 2

select *
from   #temp
where  flags & @ConditionOne <> 0

declare @ConditionTwo int = 4

select *
from   #temp
where  flags & @ConditionTwo <> 0

declare @ConditionThree int = 8

select *
from   #temp
where  flags & @ConditionThree <> 0

drop table #temp

这些查询返回以下结果集:

代码语言:javascript
复制
id          username             flags
----------- -------------------- -----------
1           User1                6
3           User3                14

id          username             flags
----------- -------------------- -----------
1           User1                6
2           User2                4
3           User3                14

id          username             flags
----------- -------------------- -----------
3           User3                14
票数 33
EN

Stack Overflow用户

发布于 2012-11-30 23:46:04

虽然James建议的按位运算符可以工作,但它在关系数据库中的性能不是很好,特别是当您试图扩展到数百万条记录时。原因是where子句中的函数不是sargable (它们阻止了索引查找)。

我要做的是创建一个表,其中包含所有可能的标志和条件组合,这将启用对条件的索引查找。

填充FlagConditions。我使用了单个(tinyint)。如果您需要更多的Flags,您应该能够扩展此方法:

代码语言:javascript
复制
CREATE TABLE FlagConditions (
      Flag TINYINT
    , Condition TINYINT
    , CONSTRAINT Flag_Condition PRIMARY KEY CLUSTERED (Condition,Flag)
);

CREATE TABLE #Flags (
      Flag TINYINT IDENTITY(0,1) PRIMARY KEY CLUSTERED
    , DummyColumn BIT NULL);
GO

INSERT #Flags
        ( DummyColumn )
SELECT NULL;
GO 256

CREATE TABLE #Conditions(Condition TINYINT PRIMARY KEY CLUSTERED);

INSERT #Conditions ( Condition )
    VALUES  (1),(2),(4),(8),(16),(32),(64),(128);

INSERT FlagConditions ( Flag, Condition )        
    SELECT
    Flag, Flag & Condition
    FROM #Flags f
    CROSS JOIN #Conditions c
    WHERE Flag & Condition <> 0;

DROP TABLE #Flags;
DROP TABLE #Conditions;

现在,您可以随时使用FlagConditions表来有效地查找枚举按位条件:

代码语言:javascript
复制
DECLARE @UserFlags TABLE (Username varchar(10), Flag tinyint);

INSERT @UserFlags(Username, Flag)
    VALUES ('User1',6),('User2',4),('User3',14);

DECLARE @Condition TINYINT = 2;

SELECT u.*
FROM @UserFlags u
INNER JOIN FlagConditions fc ON u.Flag = fc.Flag
WHERE fc.Condition = @Condition;

这将返回:

代码语言:javascript
复制
Username   Flag
---------- ----
User1      6
User3      14

您的DBA将感谢您使用这条面向集合的路线。

票数 24
EN

Stack Overflow用户

发布于 2015-11-16 22:47:30

我遇到了几乎相同的问题,并提出了这样的解决方案:

代码语言:javascript
复制
SELECT  t.value
    , ISNULL(t.C1 + ', ', '') + ISNULL(t.C2, '') + ISNULL(', ' + t.C3, '') AS [type]
FROM
(
    SELECT value,
        CASE WHEN (type & 2) <> 0  THEN 'Type1' END AS C1,
         CASE WHEN (type & 4) <> 0  THEN 'Type2' END AS C2,
         CASE WHEN (type & 8) <> 0  THEN 'Type3' END AS C3
    FROM db.Agent
) t

结果如下:

代码语言:javascript
复制
value       type
----------  ------------------------------------
14          Type1, Type2, Type3
12          Type2, Type3
14          Type1, Type2, Type3
票数 7
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13645363

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档