簡體   English   中英

將Varbinary(max)與另一個Varbinary(max)匹配

[英]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

----------------------------------------------------------
  • 一個Numbers表僅包含一個包含1到99999值的int字段
  • 96次使用,每15分鍾間隔一天(24 *(60/15))

請看下一個代碼。 它生成行並比較兩個字符串的段:

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM