我已经使用tsql了很长一段时间但是我从未在WHERE子句中看过二进制文件或oring。现在我正在开发一个可以从应用位掩码中受益的新应用程序。 可以说我有16个产品等级。每个等级由位[]列中的位位置表示。因此A109等级为0000000000000001,B704等级为0000001000000000,等级V64为0100000000000000等。任何等级在其数组列中只能有单个1。现在让我们说我可以在制造过程中将这3个等级中的每个等级相互转换。所以这个搜索的位掩码是0100001000000001。我如何写一个WHERE子句列出所有这3个等级的项目?
答案 0 :(得分:2)
在您的用户界面中,允许用户选择他喜欢的等级。在幕后,每个等级都映射到一个整数 - 来自MarkD解决方案的评分表。在应用程序中总结这些内容。将总数传递给SP。
SQL:
create procedure dbo.GetMaskedList @mask int = 0;
...
WHERE BinGrading = @mask;
UI:
int mask = 0;
foreach(item in selectList)
{
mask += item.BinScore;
}
exec GetMaskedList @mask = mask;
答案 1 :(得分:1)
对我来说也是第一次。有趣。
declare @A109 int = 1;
declare @B704 int = 512;
declare @V64 int = 16384;
declare @Xx int = 32;
declare @mask int = 16897; --@A109+@B704+@V64
create table #MyData (
name char(2),
value int);
insert #MyData
values ('a', @A109), ('b1', @B704), ('b2',@B704), ('c', @Xx);
select
name,
value
from #MyData
where (value & @mask) in (@A109, @B704, @V64);
drop table #MyData;
看来你不能对二进制数据进行按位操作! "In a bitwise operation, only one expression can be of either binary or varbinary data type"
答案 2 :(得分:1)
在这种情况下,WHERE
子句将非常简单,因为您将处理二进制数的十进制(基数10)对应物......它变得可爱,位于JOIN
。为了澄清,该方法不使用位[]列或BINARY
类型 - 仅INT
。
希望您觉得这很有帮助。
DECLARE @G1 INT = 1, -- 0000001
@G2 INT = 2, -- 0000010
@G3 INT = 4, -- 0000100
@G4 INT = 8, -- 0001000
@G5 INT = 16, -- 0010000
@G6 INT = 32, -- 0100000
@G7 INT = 64 -- 1000000
;WITH Grading (Grade, BinScore) AS
(
SELECT 'G1', 1 UNION ALL
SELECT 'G2', 2 UNION ALL
SELECT 'G3', 4 UNION ALL
SELECT 'G4', 8 UNION ALL
SELECT 'G5', 16 UNION ALL
SELECT 'G6', 32 UNION ALL
SELECT 'G7', 64
)
,Product (ProductName, BinGrading) AS
(
SELECT 'Foobar', 73 UNION ALL
SELECT 'Franglesnap', 3 UNION ALL
SELECT 'Mebble', 32
)
SELECT *
FROM Product
WHERE BinGrading = (@G1 + @G4 + @G7)
-- Alternatively...
--SELECT *
--FROM Product P
--JOIN Grading G ON P.Bingrading & G.BinScore > 0
答案 3 :(得分:1)
我做了一些更多的研究,最好的解决方案是使用按位AND运算符比较掩码
WHERE mask1 & mask2 <> 0
这很容易,简单而且有凝聚力。