在子查询中聚合按位或*分区*?
Posted
技术标签:
【中文标题】在子查询中聚合按位或*分区*?【英文标题】:Aggregate bitwise-OR in a subquery *with partitioning*? 【发布时间】:2021-08-25 16:51:53 【问题描述】:我一直在研究如何在子查询中的 TSQL 中进行按位或聚合,popular question 中给出的答案似乎并没有维护分区。有什么办法让我分区吗?
假设我们有以下数据:
id | someCount | someFlags
1 | 2 | 0
1 | 3 | 2
1 | 0 | 1
2 | 1 | 4
2 | 5 | 0
2 | 1 | 1
我可以获得由id
分区的someCount
字段的SUM
,而不会丢失任何原始行,如下所示:
SELECT [testSum] = SUM([someCount]) OVER (PARTITION BY [id]) FROM myTable
有没有办法通过按位或运算来做到这一点?所以我会得到:
id | value
1 | 3
1 | 3
1 | 3
2 | 5
2 | 5
2 | 5
【问题讨论】:
【参考方案1】:一种方法如下。将其扩展到您关心的位数。
不得不重复 PARTITION BY [id]
有点乏味,但我希望 SQL Server 只执行一次分区工作并在同一个聚合运算符中计算所有 MAX
表达式。
SELECT *,
MAX(someFlags & 1) OVER (PARTITION BY [id]) +
MAX(someFlags & 2) OVER (PARTITION BY [id]) +
MAX(someFlags & 4) OVER (PARTITION BY [id]) +
MAX(someFlags & 8) OVER (PARTITION BY [id])
FROM (VALUES
(1 , 2 , 0),
(1 , 3 , 2),
(1 , 0 , 1),
(2 , 1 , 4),
(2 , 5 , 0),
(2 , 1 , 1)
)V(id ,someCount ,someFlags)
【讨论】:
【参考方案2】:试试这个:
DECLARE @MyTable TABLE( ID int, SomeCount int, SomeFlags int)
INSERT INTO @MyTable
VALUES
(1, 2, 0)
, (1, 3, 2)
, (1, 0, 1)
, (2, 1, 4)
, (2, 5, 0)
, (2, 1, 1)
;
WITH SumTable AS
(
SELECT
iD
, TestSum = SUM(SomeCount)
, BitOrSum = SUM(SomeCount | SomeFlags)
FROM @MyTable
GROUP BY ID
)
SELECT
T.ID
, S.TestSum
, S.BitOrSum
FROM @MyTable T
JOIN SumTable S ON S.ID = T.ID
ORDER BY ID
【讨论】:
这会返回6
和 11
的 BitOrSum
- 不是正确的 3
和 5
没错。对于 ID=1:2 或 0=2; 3 或 2 = 3; 0 或 1=1。 SUM(2,3,1)=6
也许您只需要 TestSum,它是 SomeCount 的简单 SUM。这是为您提供所需结果的唯一字段,但该计算中不涉及/不需要按位或。
期望的结果来自分区中的所有值。 IE。选择 0|2|1, 4|0|1以上是关于在子查询中聚合按位或*分区*?的主要内容,如果未能解决你的问题,请参考以下文章