2014-07-11 105 views
1

像這個問題,這裏是問題摘要: 我有480種不同的鋼種。一些鋼可以通過加熱和/或化學處理轉化成另一種鋼。而且,多年來,規範和技術發生了變化,一些突變變得不可能,其他突變也變得可用我的生產環境需要自由而輕鬆地添加或刪除單個鋼種,因爲他們在db中搜索它們。如何在長二進制值(超過64位)上執行二進制壓縮

解決方案:我想使用位掩碼來提供解決方案。每種鋼材類型都會分配一個有意義的位置。可以放在一起的鋼種可以將他們的位掩碼組合起來,從而創建默認的組搜索掩碼。由於在運行時使用修改組,所以個別鋼種的位掩碼將被添加或從默認組搜索掩碼中減去。執行時,查詢將對指定表中所有項目的各個位掩碼執行二進制「與」運算,並返回所有內容,如searchMask & individualMask <> 0我成功將此原則用於其他應用程序,但SQL中的位運算符不能應用於一對二進制字段。我可以使用的最大數據類型是64位bigint。

因此,如何在T-SQL中的兩個二進制字段上執行二進制與操作,或者我可以在不創建任意組的情況下使用其他解決方案來解決上述問題?

+0

考慮用於對varbinary值進行操作的SQL CLR數據類型或函數。有了這個策略,你無論如何都無法有效地進行索引 – usr

回答

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前面的兩個塊時,CASTBIT是要確保該值可以在類型空間補充說,使用按位OR,因爲BIT無法相加。

該代碼假定這兩個值具有相同的維度,如果相反是真的@a應該是較短的一個,以減少迭代在遞歸CTE