Podczas gdy operator bitowe sugerowane przez Jamesa będzie działać, to nie będzie bardzo wydajność w relacyjnej bazie danych, zwłaszcza gdy próbujesz skalować do milionów rekordów. Powodem jest to, że funkcje w klauzuli where nie są sargable (uniemożliwiają wyszukiwanie indeksu).
Co chciałbym zrobić, to stworzyć tabelę, która zawiera wszystkie możliwe kombinacje flag i warunków, które pozwolą indeksowi na szukanie warunku.
Zapełnij warunki flagi. Użyłem singla (tinyint). Jeśli potrzebujesz więcej Flagi, powinieneś być w stanie rozwijać się na tym podejściu:
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;
Teraz można użyć tabeli FlagConditions dowolny czas potrzebny do efektywnego poszukiwania na stanie enum bitowe:
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;
Ta funkcja zwraca:
Username Flag
---------- ----
User1 6
User3 14
Twoja DBA będzie Ci wdzięczna za udanie się na tę nastawioną trasę.
To byłoby bardziej "SQL-like", aby zapisać ten informacje w tabeli wielu do wielu. Więc przechowujesz wiersze '(1,1), (1,2), (2,2), (3,1), (3,2), (3,3)' w osobnej tabeli. Zapewniłoby to bardziej naturalne zapytania i oferuje możliwości indeksowania. –