有人可以建议这种方法的良好解决方案。
我有2个长度为1024位的二进制字符串(1010101 ....)
现在我想对两者进行位操作(AND)以得到一个值是否大于0。
目前我正在将字符串转换为十六进制(256)和varbinary(128)
所以,一旦我有两个varbinary,我将每个字节转换为BIGINT,并在两个BIG INT上进行AND。
任何人都可以在SQL 2012中建议我更好的方法。
谢谢, 巴拉
答案 0 :(得分:1)
经过长时间的讨论,我终于找到了你的输入数据。你有一个varbinary(128),由一个长度为1024个字符的二进制字符串(如'1000010010101 ...')构成。 SQL Server不提供执行此类转换的就绪函数。我已经建了一个让我测试。以下函数执行此类转换:
CREATE FUNCTION dbo.binStringToBinary(@inputString VARCHAR(1024)) RETURNS VARBINARY(128) AS
BEGIN
DECLARE @inputBinary VARBINARY(128) = convert(varbinary, '', 2)
DECLARE @octet int = 1
DECLARE @len int
SET @len = Len(@inputString)
while @octet < @len
BEGIN
DECLARE @i int = 0
DECLARE @Output int = 0
WHILE(@i < 7) BEGIN
SET @Output = @Output + POWER(CAST(SUBSTRING(@inputString, @octet + @i, 1) AS int) * 2, 7 - @i)
SET @i = @i + 1
END
SET @Output = @Output + CAST(SUBSTRING(@inputString, @octet + @i, 1) AS int)
select @inputBinary = @inputBinary + convert(varbinary(1), @Output)
-- PRINT substring(@inputString, @octet, 8) + ' ' + STR(@Output, 3, 0) + ' ' + convert(varchar(1024), @inputBinary, 2)
SET @octet = @octet + 8
END
RETURN @inputBinary
END
然后我编写了一个函数,使用varbinary(128)作为输入来检查一点:
CREATE FUNCTION dbo.[DoBitsMatchFromBinary](@bitToCheck INT,@inputBinary VARBINARY(1024))
RETURNS BIT
AS
BEGIN
IF @bitToCheck < 1 OR @bitToCheck > 1024
RETURN 0
DECLARE @byte int = (@bitToCheck - 1) / 8
DECLARE @bit int = @bitToCheck - @byte * 8
DECLARE @bytemask int = POWER(2, 8-@bit)
SET @byte = @byte + 1
RETURN CASE WHEN CONVERT(int, CONVERT(binary(1), SUBSTRING(@inputBinary, @byte, 1), 2)) & @bytemask = @bytemask THEN 1 ELSE 0 END
END
作为奖励,我还在这里包含了一个从输入二进制字符串(1024)进行位检查的函数:
CREATE FUNCTION dbo.[DoBitsMatchFromBinString](@bitToCheck INT,@inputString VARCHAR(1024))
RETURNS BIT
AS
BEGIN
IF @bitToCheck < 1 OR @bitToCheck > 1024
RETURN 0
RETURN CASE WHEN SUBSTRING(@inputString, @bitToCheck, 1) = '1' THEN 1 ELSE 0 END
END
查看演示其用法的SQL fiddle。
DECLARE @inputBinary VARBINARY(128)
select @inputBinary = dbo.binStringToBinary('1010001000101111010111010100001101000100010111101011101010000101101000100010111101011101010000110100010001011110101110101000010110100010001011110101110101000011010001000101111010111010100001011010001000101111010111010100001101000100010111101011101010000101101000100010111101011101010000110100010001011110101110101000010110100010001011110101110101000011010001000101111010111010100001011010001000101111010111010100001101000100010111101011101010000101101000100010111101011101010000110100010001011110101110101000010110100010001011110101110101000011010001000101111010111010100001011010001000101111010111010100001101000100010111101011101010000101101000100010111101011101010000110100010001011110101110101000010110100010001011110101110101000011010001000101111010111010100001011010001000101111010111010100001101000100010111101011101010000101101000100010111101011101010000110100010001011110101110101000010110100010001011110101110101000011010001000101111010111010100001011010001000101111010111010100001101000100010111101011101010000101')
select dbo.[DoBitsMatchFromBinary](1, @inputBinary) bit1,
dbo.[DoBitsMatchFromBinary](2, @inputBinary) bit2,
dbo.[DoBitsMatchFromBinary](3, @inputBinary) bit3,
dbo.[DoBitsMatchFromBinary](4, @inputBinary) bit4,
dbo.[DoBitsMatchFromBinary](5, @inputBinary) bit5,
dbo.[DoBitsMatchFromBinary](6, @inputBinary) bit6,
dbo.[DoBitsMatchFromBinary](7, @inputBinary) bit7,
dbo.[DoBitsMatchFromBinary](8, @inputBinary) bit8,
dbo.[DoBitsMatchFromBinary](1017, @inputBinary) bit1017,
dbo.[DoBitsMatchFromBinary](1018, @inputBinary) bit1018,
dbo.[DoBitsMatchFromBinary](1019, @inputBinary) bit1019,
dbo.[DoBitsMatchFromBinary](1020, @inputBinary) bit1020,
dbo.[DoBitsMatchFromBinary](1021, @inputBinary) bit1021,
dbo.[DoBitsMatchFromBinary](1022, @inputBinary) bit1022,
dbo.[DoBitsMatchFromBinary](1023, @inputBinary) bit1023,
dbo.[DoBitsMatchFromBinary](1024, @inputBinary) bit1024
| bit1 | bit2 | bit3 | bit4 | bit5 | bit6 | bit7 | bit8 | bit1017 | bit1018 | bit1019 | bit1020 | bit1021 | bit1022 | bit1023 | bit1024 |
|------|-------|------|-------|-------|-------|------|-------|---------|---------|---------|---------|---------|---------|---------|---------|
| true | false | true | false | false | false | true | false | true | false | false | false | false | true | false | true |
答案 1 :(得分:1)
使用numbers table分割字符串。使用intersect进行比较并检查是否有任何行。
declare @s1 char(1024) = '01100100001',
@s2 char(1024) = '00000100001';
if exists (
select substring(@s1, N.Number, 1) as C,
N.Number
from Numbers as N
where N.Number between 1 and 1024 and
substring(@s1, N.Number, 1) = '1'
intersect
select substring(@s2, N.Number, 1) as C,
N.Number
from Numbers as N
where N.Number between 1 and 1024 and
substring(@s2, N.Number, 1) = '1'
)
begin
select 'YES'
end
else
begin
select 'NO'
end;
您获得的查询计划非常有效,并且在您匹配时会提前终止:
顶部聚集索引搜索将扫描数字表格从1到1024,并使用残差谓词检查@s1
每个位置是否有1
。对于发现的每个1
,它会在对数字表的另一个引用中进行搜索,以查看1
中该位置是否还有@s2
。找到匹配后,执行将停止。
答案 2 :(得分:1)
如果你的二进制数字可以转换为任何数字类型,这个答案可以帮助你。
<强>&安培; (按位AND)(Transact-SQL)
在两个整数值之间执行按位逻辑AND运算。
expression & expression
<强>表达强>
是整数数据类型类别,位或二进制或varbinary数据类型的任何数据类型的任何有效表达式。表达式被视为按位运算的二进制数。
注意:强>
在按位运算中,只有一个表达式可以是二进制或varbinary数据类型。
...
如果可能,您可以将其中一个表达式转换为类似bigint
的类型。
declare @b1 varbinary(max) = 0x2, @b2 varbinary(max) = 0x3
print Cast(@b1 & cast(@b2 as bigint) as varbinary(max))
结果是:
0x0000000000000002