我有一个包含一个二进制列的表。包含0x00010100000101010101 ...... 00列数据长度为35040, 我准备这样的数据,如
@Jobbyte = COALESCE(@Jobbyte , 0x) + Cast ((Case When Sum(A.bit) >= 1 then 1 else 0 end)as binary(1))
我必须将这个二进制数据与另一个二进制数据进行比较,并获得匹配的二进制数。二进制数据都具有相同的数据长度
请看下面的图像,它们是2个二进制数据Binary1和Binary2我想要比较二进制数据并获得匹配二进制数据的总和。只有一个条件是binary2的单个位是0x01
最后一行表示0 =不匹配,1 =匹配,最后一列是最后一行的总和(4) 请建议我如何比较,如果您可以发布查询,那就更好了
更新1
我正在使用2功能并尝试解决但是执行10000记录需要花费很多时间,1条记录的执行时间是50毫秒
Create FUNCTION [dbo].[Fn_BinaryToTable]
(
@BinaryData VARBINARY(max)
)
RETURNS TABLE
AS
RETURN
(
Select ((N.Number / 96) - (Case (N.Number % 96) when 0 Then 1 else 0 end))+1 As [FNNoDay],
(Case (N.Number % 96) when 0 then 96 else (N.Number % 96) end) * 15 AS [FnMinutes],
SUBSTRING(@BinaryData,(N.Number),1) AS [FNBIT]
from Numbers N
Where N.Number between 1 and (DATALENGTH(@BinaryData))
)
---------------------------------------------------------
Create FUNCTION [dbo].[fn_GetPercentage]
(
@JobValue int,
@CandidateBinary VARBINARY(max),
@JobBinary VARBINARY(max)
)
RETURNS Decimal
AS
BEGIN
DECLARE @RValue Decimal;
SELECT @RValue = SUM(cast(JB.FNBIT as int))
FROM dbo.Fn_BinaryToTable(@CandidateBinary) CB,
dbo.Fn_BinaryToTable(@JobBinary) JB
WHERE CB.FNNoDay = JB.FNNoDay
AND CB.FnMinutes = JB.FNMinutes
AND JB.FNBIT = CB.FNBIT
AND JB.FNBIT = 0x01
Return ((@RValue * 100)/ @JobValue);
END
--------------------------------------------------------
Declare @Jobbyte varbinary(max);
Declare @JobValue int;
Select @Jobbyte = JobBinary from Job;
Select @JobValue = count(*) from dbo.Fn_BinaryToTable(@Jobbyte) Where FNBIT = 0x01
----Select @JobValue = Sum(Cast(FNBIT as int)) from dbo.Fn_BinaryToTable(@Jobbyte)
set statistics time on
set statistics io on
select cid,dbo.fn_GetPercentage(@JobValue,cal,@Jobbyte) from eCal
set statistics time oFF
set statistics io oFF
----------------------------------------------------------
答案 0 :(得分:0)
请查看下一个代码。它生成行并比较两个字符串的片段:
with q as (
SELECT
CONVERT(varchar(max), a ,2) a, -- convert 'a' bin data to varchar
CONVERT(varchar(max), b ,2) b -- convert 'b' bin data to varchar
FROM
(
SELECT -- a, b - test bin data
Cast (1 as binary(1)) + Cast (0 as binary(1)) + Cast (1 as binary(1)) a, -- 01 00 01
Cast (1 as binary(1)) + Cast (1 as binary(1)) + Cast (1 as binary(1)) b -- 01 01 01 - 2 matches
) k
)
select
--*, substring(a, x + 1, 2), substring(b, x + 1, 2)
sum(case when
substring(a, x + 1, 2) = substring(b, x + 1, 2) -- is block equals
then 1 else 0 end) sum_of_all_pair_equals
from
q
join
( -- generate 99999 rows for getting 2 chars block from staring a, b
select
x * 10000 + y * 1000 + z * 100 + k * 10 + l as x
from
(select 1 x union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) x,
(select 1 y union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) y,
(select 1 z union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) z,
(select 1 k union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) k,
(select 1 l union select 2 union select 3 union select 4 union select 5 union select 6 union select 7 union select 8 union select 9 union select 0) l
) x
on (
x between 0 and len(a) - 2 -- start from 1 to len - 2
and x % 2 = 0 -- get every even x
)
此查询必须更快,但我还没有测试它的性能:
DECLARE @a VARCHAR(30); -- a bin string
DECLARE @b VARCHAR(30); -- b bin string
DECLARE @itersLeft INT; -- iterations count
DECLARE @i INT; -- counter
DECLARE @outCnt INT; -- result match counter
SELECT
@a = CONVERT(varchar(max), a ,2), -- convert 'a' bin data to varchar
@b = CONVERT(varchar(max), b ,2) -- convert 'b' bin data to varchar
FROM
(
SELECT -- a, b - test bin data
Cast (1 as binary(1)) + Cast (0 as binary(1)) + Cast (1 as binary(1)) a, -- 01 00 01
Cast (1 as binary(1)) + Cast (1 as binary(1)) + Cast (1 as binary(1)) b -- 01 01 01 - 2 matches
) k
;
SET @i = 0; -- init counter
SET @outCnt = 0; -- init result counter
SELECT @itersLeft = LEN(@a) - 2; -- setting max iterations counter
WHILE @i <= @itersLeft
BEGIN
if substring(@a, @i + 1, 2) = substring(@b, @i + 1, 2) -- compare data
SET @outCnt = @outCnt + 1; -- increase counter if equals
SET @i = @i + 2; -- increase counter by block size
END
SELECT @outCnt result; -- selecting result