【问题标题】:SQL Server: Use multiple aggregate/analytic functions with same OVER clause?SQL Server:使用具有相同 OVER 子句的多个聚合/分析函数?
【发布时间】: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;

我怀疑它对每个聚合(AVGPERCENTILE_CONTMAX)都进行了冗余分区。有没有办法只编写一次OVER 子句并将其应用于每个聚合?

【问题讨论】:

  • 使用OVER 子句的函数不是聚合函数...
  • Edit问题并提供minimal reproducible example,即表和索引的CREATE语句(粘贴文本,不要使用图像), INSERT 用于示例数据 (dito) 的语句、表格文本格式的示例数据的期望结果以及您的查询的当前计划。
  • @MarkPundurs,使用多余的PARTITION BY 子句不一定会导致执行多余的工作。你能分享你的查询计划吗?
  • 几乎可以肯定是DISTINCT 给您带来了问题。为什么它首先存在,从外观上看,你真的想要一个具有正常聚合的GROUP BY。完全相同的PARTITION BY 多次几乎肯定不会多次计算分区,只有实际函数会

标签: sql-server tsql aggregate-functions


【解决方案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;

【讨论】:

  • 谢谢,丹尼尔!
猜你喜欢
  • 2016-01-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-09-07
  • 2012-12-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多