55

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

ユーザーテーブル
----------
ID ユーザー名の役割
1 デイブ 6
2 チャーリー 2
3 スーザン 4
4 ニック 1

役割表
-----------
ID ロール
1 管理者
2 プログラマー
4 デザイナー

何か案は?ありがとう。

4

6 に答える 6

93

あなたの質問への答えは、次の&ように Bitwise を使用することです。

SELECT * FROM UserTable WHERE Roles & 6 != 0

ユーザーがそれらのビットの 1 つ以上を持っていることを確認したい場合は、ビットフィールドの6任意の組み合わせと交換できます。これを検証しようとするとき、私は通常、これをバイナリで手書きで書き出すと役立つと思います。ユーザーテーブルは次のようになります。

        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
于 2012-02-13T15:36:36.120 に答える
6

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

于 2008-09-27T14:41:22.613 に答える
5
SELECT * FROM UserTable WHERE Roles & 6 > 0
于 2012-02-13T14:59:04.043 に答える
2

SELECT *FROMテーブルWHEREmask1&mask2> 0

于 2010-08-24T22:28:13.943 に答える
2

例:

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
于 2010-08-24T23:21:08.533 に答える
0

すべてのプログラマーを見つけるには、次を使用します。

SELECT * FROM UserTable WHERE Roles & 2 = 2
于 2008-09-27T16:08:34.247 に答える