喜欢这个主题,这里是问题简介: 我有480种不同的钢种。一些钢可以通过加热和/或化学处理转化为另一种钢。此外,多年来规范和技术发生变化,一些突变变得不可能,其他突变变得可用。我的生产环境需要在db中搜索它们时自由而轻松地添加或删除单个钢种。
解决方案:我想使用位掩码来提供解决方案。每种钢种都将分配单独的有效钻头位置。可以组合在一起的钢类型将其位掩码组合在一起,创建默认的组搜索掩码。当使用在运行时修改组时,将从默认组搜索掩码中添加或减去单个钢类型的位掩码。执行时,查询将针对指定表中所有项的各个位掩码执行二进制AND运算并返回所有类似searchMask & individualMask <> 0
我成功将此原则用于其他应用程序但SQL中的位运算符不能应用于一对二进制字段。我可以使用的最大数据类型是64位bigint。
因此,问题是,如何在T-SQL中对两个二进制字段执行二进制AND运算,或者我可以使用哪些其他解决方案来解决上述问题而不创建任意组?
答案 0 :(得分:1)
一个想法可以是将掩码分成64位的块并分别检查每一个chunck然后添加按位运算的结果,可以转换为函数的概念证明
DECLARE @a VARBINARY(200) = Cast(Replicate(Char(128), 200) AS VARBINARY(200))
DECLARE @b VARBINARY(200) = Cast(Replicate(Char(130), 200) AS VARBINARY(200));
WITH splitter AS (
SELECT Cast(Cast(LEFT(@a, 64) AS VARBINARY(64)) AS BIGINT) a
, Cast(Cast(LEFT(@b, 64) AS VARBINARY(64)) AS BIGINT) b
, _and = Cast(0 AS BIT)
, b = 1
, rev = Cast(Ceiling(Len(@a) / 64.0) AS INT)
UNION ALL
SELECT Cast(Cast(Substring(@a, b * 64, 64) AS VARBINARY(64)) AS BIGINT) a
, Cast(Cast(Substring(@b, b * 64, 64) AS VARBINARY(64)) AS BIGINT) b
, _and = _and | Cast(a & b AS BIT),
, b = b + 1,
, rev = rev - 1
FROM splitter
WHERE b * 64 < Len(@a)
)
SELECT _and | Cast(a & b AS BIT)
FROM splitter
WHERE rev = 1
递归CTE
,有很多CAST
,每64字节生成一行,并按位AND
执行前两个块,CAST
到BIT
要确保可以在类型空间中添加值,使用按位OR
,因为BIT
无法求和。
代码假设两个值具有相同的维度,如果相反,则@a应该是较短的值,以便在递归CTE
中具有较少的迭代。