在窗口功能中使用DISTINCT和OVER


18

我正在尝试将查询从Oracle迁移到SQL Server 2014。

这是我的查询,在Oracle中效果很好:

select
count(distinct A) over (partition by B) / count(*) over() as A_B
from MyTable 

这是我尝试在SQL Server 2014中运行此查询后遇到的错误。

Use of DISTINCT is not allowed with the OVER clause

有人知道是什么问题吗?在SQL Server中可以进行这种查询吗?请指教。


实际每行结果需要一行MyTable吗?还是不同的行足够?而且,如果其中没有行,则无需考虑除零错误MyTable
Erwin Brandstetter

Answers:


12

有人知道是什么问题吗?在SQL Server中可以进行这种查询吗?

不,目前尚未实现。请参阅以下连接项目请求。

OVER子句增强请求-聚合函数的DISTINCT子句

另一个可能的变体是

SELECT M.A,
       M.B,
       T.A_B
FROM   MyTable M
       JOIN (SELECT CAST(COUNT(DISTINCT A) AS NUMERIC(18,8)) / SUM(COUNT(*)) OVER() AS A_B,
                    B
             FROM   MyTable
             GROUP  BY B) T
         ON EXISTS (SELECT M.B INTERSECT SELECT T.B) 

强制转换NUMERIC为避免整数除法。此处说明 join子句的原因。

如果需要,可以将其替换ON M.B = T.B OR (M.B IS NULL AND T.B IS NULL)(或者ON M.B = T.B如果该B列不可为空,则可以将其替换)。


14

这给出了由B划分的A的不同count(*):

dense_rank() over (partition by B order by A) 
+ dense_rank() over (partition by B order by A desc) 
- 1

3
有趣的解决方案。我想它应该有一个免责声明,即它A仅在不可为空时才起作用(因为我认为它也计为null)。
ypercubeᵀᴹ

我应该abs(dense_rank - dense_rank) + 1相信。
norcalli

7

您可以取的最大值dense_rank()来获得由B划分的A的唯一计数。

要处理A可以具有null值的情况,可以使用first_value该方法确定分区中是否存在null,然后按照Martin Smith在评论中的建议将其减去1。

select (max(T.DenseRankA) over(partition by T.B) - 
          cast(iif(T.FirstA is null, 1, 0) as numeric(18, 8))) / T.TotalCount as A_B
from (
     select dense_rank() over(partition by T.B order by T.A) DenseRankA,
            first_value(T.A) over(partition by T.B order by T.A) as FirstA,
            count(*) over() as TotalCount,
            T.A,
            T.B
     from MyTable as T
     ) as T

5

尝试执行子查询,按A,B分组并包括计数。然后在外部查询中,count(distinct)变为常规计数,而count(*)成为sum(cnt)。

select
count(A) over (partition by B) * 1.0 / 
    sum(cnt) over() as A_B
from
(select A, B, count(*) as cnt
 from MyTable
 group by A, B) as partial;
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.