如何解决如何将逻辑 OR 应用于 BINARY 列,以便结果是所有正确的值?
我有一组存储在 binary(12) 列中的结果。我正在寻找在不同时间为特定条件设置的所有标志。它类似于
状态 | 标志 |
---|---|
1234 | 0x000000000000000000002000 |
5678 | 0x000000000000000000000000 |
1234 | 0x000000000000000000000040 |
SELECT Status,OR(Flags)
FROM StatusTable
GROUP BY Status
给出结果
状态 | OR(Flags) |
---|---|
1234 | 0x000000000000000000002040 |
5678 | 0x000000000000000000000000 |
我可以找到让我手动对两个值进行 OR 运算但没有将 OR 应用于结果列的示例。我已经大大简化了这个例子,但我们正在谈论具有数千种状态(主要是 0x000000000000000000000000)的数千个值,因此手动 OR 它们是不切实际的。我想可以使用一个函数和一个游标来循环每个函数,但肯定有一个开箱即用的解决方案吗?
解决方法
用 TSQL 写这个会很困难,如果你不能修复底层设计,你可以写一个 .Net CLR User-Defined Aggregate。
在 C# 中,您有二元 OR 运算符:Bitwise and shift operators。
您可以按照本指南编写 CLR 函数: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,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],v2.bitt
) t
GROUP BY Status
步骤如下:
- 取基表,交叉连接每个 32 位整数的
1,5,9
起始字节数。 - 再次交叉连接所有位标志
- 按
Status
和位置/标志分组 - 选择
Status
、整数位置以及是否有任何值设置了此标志 - 最后有条件地总结标志并将结果转换回二进制
如果您想实现 AND
聚合,请将 MAX
更改为 MIN
。
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。