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

StackOverflow https://stackoverflow.com/questions/143712

  •  02-07-2019
  •  | 
  •  

質問

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

User Table
----------
ID  Username  Roles
1   Dave      6
2   Charlie   2
3   Susan     4
4   Nick      1

Roles Table
-----------
ID  Role
1   Admin
2   Programmer
4   Designer

アイデアはありますか?ありがとう。

役に立ちましたか?

解決

質問に対する答えは、次のようにビット単位の& を使用することです。

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

bitwaiseを実行している各ユーザーを確認すると、テストに対して次のようになります:

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

SELECT * FROM UserTable WHERE Roles & 6 > 0

SELECT * FROMテーブルWHERE mask1& mask2> 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 UserTable WHERE Roles & 2 = 2
ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top