Transact-SQLの2つのビットマスクを比較して、いずれかのビットが一致するかどうかを確認する方法はありますか?ユーザーが属するすべてのロールのビットマスクを持つUserテーブルがあり、提供されたビットマスクでanyのロールを持つすべてのユーザーを選択したいと思います。したがって、以下のデータを使用すると、ロールマスク6(デザイナー+プログラマー)は、Dave、Charlie、Susanを選択する必要がありますが、Nickは選択しません。
ユーザーテーブル ---------- IDユーザー名ロール 1デイブ6 2チャーリー2 3スーザン4 4ニック1 ロールテーブル ----------- IDロール 1管理者 2プログラマー 4デザイナー
何か案は?ありがとう。
あなたの質問に対する答えは、Bitwise &
このような:
SELECT * FROM UserTable WHERE Roles & 6 != 0
6
は、ユーザーがこれらのビットを1つ以上持っていることを確認したいビットフィールドの任意の組み合わせに交換できます。これを検証しようとするとき、私は通常、これをバイナリで手書きで書くのが役立つと思います。ユーザーテーブルは次のようになります。
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
私たちがビットワイズをしている各人を通過すると、テストに対してこれらが得られます:
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)
上記は、結果がゼロでないレコードには、要求されたフラグが1つ以上あることを示す必要があります。
編集:これを確認したい場合のテストケースを次に示します。
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
または
select * from test where (roles & 2) != 0 // returns Dave & Charlie
または
select * from test where (roles & 7) != 0 // returns dave, charlie, susan & nick
Transact-SQL ビットごとのAND演算子 "&"を使用して、結果をゼロと比較します。さらに良いことに、ロールを整数列のビットとしてコーディングする代わりに、ロールごとにブール列を使用します。その場合、クエリは単にデザイナーであり、プログラマーにとって使いやすいものになります。ロールがアプリケーションの存続期間中に大きく変化すると予想される場合は、多対多のテーブルを使用して、ユーザーとそのロールの間の関連付けをマップします。どちらの選択肢も、ビット単位のAND演算子の存在に依存するよりも移植性があります。
SELECT * FROM UserTable WHERE Roles & 6 > 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テーブルWHERE mask1&mask2> 0
すべてのプログラマを見つけるには:
SELECT * FROM UserTable WHERE Roles & 2 = 2