在子查询中聚合按位或*分区*?

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

【讨论】:

这会返回 611BitOrSum - 不是正确的 35 没错。对于 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

以上是关于在子查询中聚合按位或*分区*?的主要内容,如果未能解决你的问题,请参考以下文章

在子查询、标准或 Oracle 功能中混合聚合值和非聚合值?

结果之间的按位或

如何在子查询中使用外部查询中的列从另一个表中获取结果?

SQL 中 where 后面可不可以跟上子查询

SQL Server - 在子查询中使用主查询中的列

子序列的按位或 Bitwise ORs of Subarrays