web-dev-qa-db-ja.com

SQLの2つのビットマスクを比較して、いずれかのビットが一致するかどうかを確認する

Transact-SQLの2つのビットマスクを比較して、いずれかのビットが一致するかどうかを確認する方法はありますか?ユーザーが属するすべてのロールのビットマスクを持つUserテーブルがあり、提供されたビットマスクでanyのロールを持つすべてのユーザーを選択したいと思います。したがって、以下のデータを使用すると、ロールマスク6(デザイナー+プログラマー)は、Dave、Charlie、Susanを選択する必要がありますが、Nickは選択しません。

ユーザーテーブル
 ---------- 
 IDユーザー名ロール
 1デイブ6 
 2チャーリー2 
 3スーザン4 
 4ニック1 
 
ロールテーブル
 ----------- 
 IDロール
 1管理者
 2プログラマー
 4デザイナー

何か案は?ありがとう。

47
Nick

あなたの質問に対する答えは、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
77
Jamiec

Transact-SQL ビットごとのAND演算子 "&"を使用して、結果をゼロと比較します。さらに良いことに、ロールを整数列のビットとしてコーディングする代わりに、ロールごとにブール列を使用します。その場合、クエリは単にデザイナーであり、プログラマーにとって使いやすいものになります。ロールがアプリケーションの存続期間中に大きく変化すると予想される場合は、多対多のテーブルを使用して、ユーザーとそのロールの間の関連付けをマップします。どちらの選択肢も、ビット単位のAND演算子の存在に依存するよりも移植性があります。

6
SELECT * FROM UserTable WHERE Roles & 6 > 0
5
Ben

例:

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
2
ScottE

SELECT * FROMテーブルWHERE mask1&mask2> 0

2
vsevik

すべてのプログラマを見つけるには:

SELECT * FROM UserTable WHERE Roles & 2 = 2
0
Sklivvz