我用的是旗上枚举在C#中,一切都很好,但希望使用类似的SQL东西在以下情形:
我们要返回的列表或条件,像这样的一部分用户的列表:
ConditionOne = 2
ConditionTwo = 4
ConditionThree = 8
等等...
我们将有一些对他们的这些条件,像这样的用户:
User1: 6 (conditions 1 and 2)
User2: 4 (condition 2)
User3: 14 (conditions 1, 2 and 3)
等等...
我们希望能够做一个查询,我们说让所有用户都使用条件1和在这种情况下它会返回用户1和3,即使他们有其他条件也是如此。
任何有识之士将不胜感激,只有直接使用标志在C#中,而不是在SQL Server中。
在SQL中的位运算符是&
。 在WHERE
子句中需要评估的BOOLEAN
表达式,像这样:
create table #temp (id int, username varchar(20), flags int)
insert into #temp values
(1, 'User1', 6),
(2, 'User2', 4),
(3, 'User3', 14)
declare @ConditionOne int = 2
select *
from #temp
where flags & @ConditionOne <> 0
drop table #temp
该查询返回以下数据集:
id username flags
----------- -------------------- -----------
1 User1 6
3 User3 14
虽然詹姆斯提出的位运算符将工作,它不会在关系数据库非常高性能的,尤其是当你尝试扩展到数百万的记录。 其原因是,在where子句中函数不是可优化搜索(它们阻止索引查找)。
我会做的是创建一个包含标志和条件的所有可能的组合,这将使指数的条件寻求表。
填充FlagConditions。 我用单个(TINYINT)。 如果您需要更多的标志,你应该能够对这种做法扩大:
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表中,您需要在枚举按位条件有效地寻求任何时间:
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;
这将返回:
Username Flag
---------- ----
User1 6
User3 14
你的DBA会感谢你走这组面向路线。
我几乎同样的问题,能想出这样的解决方案:
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
其结果如下:
value type
---------- ------------------------------------
14 Type1, Type2, Type3
12 Type2, Type3
14 Type1, Type2, Type3
C#枚举: CopEntry = 1 << 17
SQL服务器: case when (Features & power(2, 17)) = 0 then 0 else 1 end as COPEntry