[英]Match Varbinary(max) with another Varbinary(max)
我有一個帶有一個二進制列的表。 包含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條記錄執行需要很多時間,一條記錄的執行時間是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
----------------------------------------------------------
請看下一個代碼。 它生成行並比較兩個字符串的段:
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
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.