【问题标题】:How to optimise an SQL query that use multiple subqueries and aggregate functions?如何优化使用多个子查询和聚合函数的 SQL 查询?
【发布时间】:2015-03-10 01:07:56
【问题描述】:

我有一个如下的 SQL 查询。它可以达到目的,但速度很慢而且有点复杂,因为它有许多聚合函数和子查询。我觉得它很复杂而且很慢。

这里是查询:

SELECT
    dd.period,
    DATEADD(day,1,DATEADD(month,-12,MAX(dso.date_clearing))) AS startdate, 
    MAX(dso.date_clearing) AS lastdate, 
    ROUND(SUM(dso.DSO_actual_calc)/SUM(dso.amount_received_group_currency),1) AS dso,
    ROUND(SUM(dso.DSO_overdue_calc)/SUM(dso.amount_received_group_currency),1) AS dsooverdue,
   (SELECT
        ROUND(SUM(dso1.DSO_actual_calc)/SUM(dso1.amount_received_group_currency),1)
    FROM fact_dso_cleared_items as dso1
        INNER JOIN dim_date dd1
            ON dso1.date_clearing = dd1.the_date
    WHERE dso1.date_clearing BETWEEN
        DATEADD(day,1,DATEADD(month,-12,MAX(dso.date_clearing)))
             AND MAX(dso.date_clearing))) AS dso_rltm,
   (SELECT
        ROUND(SUM(dso2.DSO_overdue_calc)/SUM(dso2.amount_received_group_currency), 1)
    FROM fact_dso_cleared_items as dso2
        INNER JOIN dim_date as dd2
            ON dso2.date_clearing = dd2.the_date
    WHERE dso2.date_clearing BETWEEN
        DATEADD(day,1,DATEADD(month,-12,MAX(dso.date_clearing)))
        AND MAX(dso.date_clearing))) AS dso_overdue_rltm
FROM fact_dso_cleared_items AS dso
    INNER JOIN dim_date dd
        ON dso.date_clearing = dd.the_date
WHERE dd.period IN('2012/01','2012/02','2012/03','2012/04','2012/05','2012/06',
                   '2012/07','2012/08','2012/09','2012/10','2012/11','2012/12'))
GROUP BY dd.period
ORDER BY dd.period

这是显示表和字段的查询图表。

这里是这个查询的结果。

为了简化和提高性能,我应该在此查询中开始改进哪些方面?

【问题讨论】:

  • 谢谢!您能否描述一下您要做什么,这两个表中的一些示例数据也会有所帮助。确保样本数据和预期结果匹配。

标签: sql sql-server performance tsql


【解决方案1】:

第一次尝试。我试图杀死多个聚合函数,因为您多次使用DATEADD(Day, 1, DATEADD(Month, -12, MAX(dso.date_clearing)))。我认为with 查询会有所帮助。

第一次尝试。

SELECT *

    ,dso_rltm           = (SELECT ROUND(SUM(dso1.DSO_actual_calc) / SUM(dso1.amount_received_group_currency), 1)
                           FROM fact_dso_cleared_items as dso1
                           INNER JOIN dim_date dd1 ON dso1.date_clearing = dd1.the_date
                           WHERE dso1.date_clearing BETWEEN data.startdate AND data.lastdate)

   ,dso_overdue_rltm    = (SELECT ROUND(SUM(dso2.DSO_overdue_calc) / SUM(dso2.amount_received_group_currency), 1)
                           FROM fact_dso_cleared_items as dso2
                           INNER JOIN dim_date as dd2 ON dso2.date_clearing = dd2.the_date 
                           WHERE dso2.date_clearing BETWEEN data.startdate AND data.lastdate)
FROM (
    SELECT

         period     = dd.period
        ,startdate  = DATEADD(Day, 1, DATEADD(Month, -12, MAX(dso.date_clearing))) 
        ,lastdate   = MAX(dso.date_clearing) 
        ,dso        = ROUND(SUM(dso.DSO_actual_calc) / SUM(dso.amount_received_group_currency), 1)
        ,dsooverdue = ROUND(SUM(dso.DSO_overdue_calc) / SUM(dso.amount_received_group_currency), 1)

    FROM fact_dso_cleared_items AS dso
    INNER JOIN dim_date dd ON dso.date_clearing = dd.the_date
    WHERE dd.period IN('2012/01','2012/02','2012/03','2012/04','2012/05','2012/06','2012/07','2012/08','2012/09','2012/10','2012/11','2012/12'))
    GROUP BY dd.period
    ) data
ORDER BY data.period

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-09
    • 1970-01-01
    • 2020-05-13
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-09-27
    相关资源
    最近更新 更多