SQL Server:使用具有相同 OVER 子句的多个聚合/分析函数?
Posted
技术标签:
【中文标题】SQL Server:使用具有相同 OVER 子句的多个聚合/分析函数?【英文标题】:SQL Server: Use multiple aggregate/analytic functions with same OVER clause? 【发布时间】:2021-06-29 12:02:48 【问题描述】:以下 SQL Server 查询:
SELECT DISTINCT NodeID, dateadd(hour, datediff(hour, 0, Timestamp), 0) as dt_hour
,AVG(Availability)
OVER (PARTITION BY NodeID, dateadd(hour, datediff(hour, 0, Timestamp), 0)) AS avg
,PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY Availability)
OVER (PARTITION BY NodeID, dateadd(hour, datediff(hour, 0, Timestamp), 0)) AS perc90
,MAX(Availability)
OVER (PARTITION BY NodeID, dateadd(hour, datediff(hour, 0, Timestamp), 0)) AS max
FROM InterfaceAvailability_CS_Detail_hist
order by NodeID, dt_hour;
运行时间大约是这个的 3 倍:
SELECT DISTINCT NodeID, dateadd(hour, datediff(hour, 0, Timestamp), 0) as dt_hour
,PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY Availability)
OVER (PARTITION BY NodeID, dateadd(hour, datediff(hour, 0, Timestamp), 0)) AS perc90
FROM InterfaceAvailability_CS_Detail_hist
order by NodeID, dt_hour;
我怀疑它对每个聚合(AVG
、PERCENTILE_CONT
、MAX
)都进行了冗余分区。有没有办法只编写一次OVER
子句并将其应用于每个聚合?
【问题讨论】:
使用OVER
子句的函数不是聚合函数...
Edit问题并提供minimal reproducible example,即表和索引的CREATE
语句(粘贴文本,不要使用图像), INSERT
用于示例数据 (dito) 的语句、表格文本格式的示例数据的期望结果以及您的查询的当前计划。
"OVER 子句可能跟在所有聚合函数后面" - https://docs.microsoft.com/en-us/sql/t-sql/functions/aggregate-functions-transact-sql
@MarkPundurs,使用多余的PARTITION BY
子句不一定会导致执行多余的工作。你能分享你的查询计划吗?
几乎可以肯定是DISTINCT
给您带来了问题。为什么它首先存在,从外观上看,你真的想要一个具有正常聚合的GROUP BY
。完全相同的PARTITION BY
多次几乎肯定不会多次计算分区,只有实际函数会
【参考方案1】:
如果没有看到查询计划,很难知道发生了什么,但我的猜测是,通过在 parititon by 子句中使用标量函数,您限制了 sql server 可以做哪些优化查询。
我尝试了一个类似的查询,并通过使用 CTE 为 dt_hour 列生成值,我能够生成一个具有较少排序、嵌套循环和流聚合操作的计划。由于我不知道原始查询中这些操作的成本,我不知道这是否会产生更好的结果,因为在计划中看到更少的东西并不一定意味着改进。
WITH processed AS (
SELECT *, dateadd(hour, datediff(hour, 0, Timestamp), 0) as dt_hour
FROM InterfaceAvailability_CS_Detail_hist
)
SELECT DISTINCT NodeID, dt_hour
,AVG(Availability)
OVER (PARTITION BY NodeID, dt_hour) AS avg
,PERCENTILE_CONT(0.9) WITHIN GROUP (ORDER BY Availability)
OVER (PARTITION BY NodeID, dt_hour) AS perc90
,MAX(Availability)
OVER (PARTITION BY NodeID, dt_hour) AS max
FROM processed
order by NodeID, dt_hour;
【讨论】:
谢谢,丹尼尔!以上是关于SQL Server:使用具有相同 OVER 子句的多个聚合/分析函数?的主要内容,如果未能解决你的问题,请参考以下文章
如何使用具有相同值的 OVER 子句的 SUM 函数按列返回正确的总和?