T-SQL 不擅长处理比特。但它确实有&
和|
。您需要分解每个标志,将其汇总在表格上,然后将其重新打包
由于缺少 binary ,这个查询并没有变得更容易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
步骤如下:
- 以基表为例,交叉连接
1,5,9
每个 32 位整数的起始字节数。
- 再次交叉加入所有位标志
- 分组依据
Status
和位置/标志
- 选择
Status
, Integer 位置,以及是否有任何值设置了此标志
- 最后有条件地总结标志并将结果转换回二进制
如果您想将AND
聚合更改MAX
为MIN
.