簡體   English   中英

如何將邏輯 OR 應用於 BINARY 列,以便結果是所有正確的值?

[英]How can I apply a logical OR to a BINARY column so the result is all the correct values?

我有一組存儲在 binary(12) 列中的結果。 我正在尋找針對特定條件在不同時間設置的所有標志。 它就像

地位 標志
1234 0x000000000000000000002000
5678 0x0000000000000000000000000
1234 0x0000000000000000000000040

我想做的是寫一個查詢,例如

SELECT Status, OR(Flags)
FROM StatusTable
GROUP BY Status

給出結果

地位 或(標志)
1234 0x0000000000000000000002040
5678 0x0000000000000000000000000

我可以找到讓我手動 OR 兩個值但沒有將 OR 應用於結果列的示例。 我已經大大簡化了這個例子,但我們正在談論數千個具有數千個狀態的值(主要是 0x000000000000000000000000),這使得手動或它們是不切實際的。 我想可以使用 function 和 cursor 來循環每個,但肯定有一個開箱即用的解決方案嗎?

在 TSQL 中寫這個很難,如果你不能修復底層設計,你可以寫一個.Net CLR 用戶定義的聚合。

在 C# 中,您有二進制 OR 運算符: 按位和移位運算符
您可以按照本指南編寫 CLR function: CLR User-Defined Aggregates

T-SQL 不擅長處理比特。 但它確實有&| . 您需要分解每個標志,將其匯總在表格上,然后將其重新打包

由於缺少二進制STRING_AGG ,這個查詢並沒有變得更容易。

SELECT
    [Status],
    CAST(SUM(CASE WHEN byte = 1 THEN val END) AS binary(4)) +
    CAST(SUM(CASE WHEN byte = 5 THEN val END) AS binary(4)) +
    CAST(SUM(CASE WHEN byte = 9 THEN val END) AS binary(4)) AS OrFlags
FROM (
    SELECT [Status], v1.bytePos,
        MAX(CASE WHEN CAST(SUBSTRING(Flags, v1.bytePos, 4) AS int) & v2.bitt <> 0 THEN v2.bitt ELSE 0 END) AS val
    FROM @StatusTable
    CROSS JOIN (VALUES(1),(5),(9)) v1(bytePos)
    CROSS JOIN (VALUES
        (1),(2),(4),(8),(16),(32),(64),(128),(256),(512),(1024),(2048),(4096),(8192),(16384),(32768),(65536),(131072),(262144),(524288),(1048576),(2097152),(4194304),(8388608),(16777216),(33554432),(67108864),(134217728),(268435456),(536870912),(1073741824),(-2147483648)
    ) v2(bitt)
    GROUP BY [Status], v1.bytePos, v2.bitt
) t
GROUP BY Status

步驟如下:

  • 以基表為例,為每個 32 位 Integer 交叉連接1,5,9起始字節數。
  • 再次交叉加入所有位標志
  • Status和位置/標志分組
  • Select 出Status ,Integer position,以及是否有任何值設置了這個標志
  • 最后有條件地總結標志並將結果轉換回二進制

如果要實現AND聚合,請將MAX更改為MIN

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

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