【问题标题】:aggregation in subqueries using Outer reference inside case. Getting Error使用外部引用内部案例聚合子查询。出现错误
【发布时间】:2019-02-21 13:40:17
【问题描述】:

这只是我完整查询的一小部分

我有一些数据正在使用聚合和子查询计算今年和去年(很多其他事情)的值。

下面是我的查询的工作和最简单的版本:

SELECT distinct 
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
(SELECT SUM(value) FROM data  ----- value is the column name which i want to aggregate 
    WHERE mar_short_desc = t1.mar_short_desc
    AND category = t1.category
    AND manufacturer = t1.manufacturer
    AND month = t1.month
    AND year = t1.year ----- This Is the only difference Filter
) AS Company_TY, 
(SELECT SUM(value) FROM data  
    WHERE mar_short_desc = t1.mar_short_desc
    AND category = t1.category
    AND manufacturer = t1.manufacturer
    AND month = t1.month
    AND year = t1.year -1  ----- This Is the only difference Filter
) AS Company_LY,
FROM data  t1
----- Other filters are here ignored for simplicity 
) a

我想优化它。因此尝试将两个子查询合并为一个并使用“case”语句来计算相同的值。

这是修改后的版本:

SELECT distinct
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
(SELECT SUM(CASE WHEN year = t1.year THEN value END) AS Company_TY,
        SUM(CASE WHEN year = t1.year -1 THEN value END) AS company_LY 
FROM data
    WHERE mar_short_desc = t1.mar_short_desc
    AND category = t1.category
    AND manufacturer = t1.manufacturer
    AND month = t1.month
)
FROM data  t1
) a 

这给了我错误:“在一个 包含外部引用的聚合表达式。如果一个表达式 被聚合包含一个外部引用,然后那个外部 reference 必须是表达式中唯一引用的列。"

我要做的就是制作一个包含所有常见过滤器的框架,然后使用唯一过滤器聚合该结果(原因:所以我不必一次又一次地过滤相同的东西。它是一个大代码和很多数据如此,要优化)

【问题讨论】:

  • MAX 和 SUM 不是一回事。您可以通过将示例数据和预期输出作为文本添加到问题中来改进此问题。
  • 你的第二个查询真的优化了吗?如果数据库中有 15 年的数据怎么办?您可能必须扫描所有 15 年并丢弃其中的 13 年。
  • @P.Salmon 也更新了上面的 SUM()。我想要从第一个查询中得到的结果。它是一个简单的 Over + partion By + 另一个过滤器,在该过滤器中获得了去年同月的值。值得一提的是,这只是 8000 行查询中的一部分,其中包含 10GB 数据和 20 列。
  • 选择DISTINCT a, b 然后使用相同的列进行相关子查询是很奇怪的。至少第一个子查询似乎是不必要的。
  • @WillisBlackburn 当我有 10 GB 的数据并且我必须为每一行执行这些过滤器并且必须通过这样的子查询 20 次(没有任何其他方式〜或者我不知道学习阶段)我认为它的一次过滤和计算比做同样的 20 次更好。有关如何解决此参考问题的任何建议?

标签: sql sql-server case correlated-subquery


【解决方案1】:

为了优化,请考虑避免 SELECT 中的相关子查询和简单的 JOIN 主表到派生表。这应该更有效,因为聚合只运行一次,而不是针对外部查询中的每一行。

由于年份匹配不同,下面使用了两个派生表。虽然添加了GROUP BY 子句更加冗长,但它应该比来自第一个 SQL 代码块的相关子查询运行得更好。甚至为连接字段添加索引以提高性能。

SELECT distinct
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
       sub1.Company_TY,
       sub2.Company_LY
FROM data  t1
INNER JOIN
   (SELECT mar_short_desc, category,  manufacturer, month, year,
           SUM(value) AS Company_TY
    FROM data 
    GROUP BY mar_short_desc, category, manufacturer, month, year
   ) sub1
ON sub1.mar_short_desc = t1.mar_short_desc
AND sub1.category = t1.category
AND sub1.manufacturer = t1.manufacturer
AND sub1.month = t1.month
AND sub1.year = t1.year

INNER JOIN
   (SELECT mar_short_desc, category,  manufacturer, month, year,
           SUM(value) AS Company_LY
    FROM data 
    GROUP BY mar_short_desc, category, manufacturer, month, year
   ) sub2
ON sub2.mar_short_desc = t1.mar_short_desc
AND sub2.category = t1.category
AND sub2.manufacturer = t1.manufacturer
AND sub2.month = t1.month
AND sub2.year = t1.year - 1

【讨论】:

    【解决方案2】:

    在您的原始示例中,您有两列由内部查询返回到外部查询,如果您弹出一列并将另一列留在子查询中,它可能会起作用。我不确定您使用的 distinct 子句将如何处理。

    SELECT distinct
       t1.country,
       t1.manufacturer,
       t1.category,
       t1.month, 
       t1.year,
       SUM(CASE WHEN year = t1.year THEN value END) AS Company_TY,
       (SELECT SUM(CASE WHEN year = t1.year -1 THEN value END) AS company_LY 
            FROM data
                WHERE mar_short_desc = t1.mar_short_desc
                AND category = t1.category
                AND manufacturer = t1.manufacturer
                AND month = t1.month
            )
    FROM data  t1
    ) a 
    

    也试试下面的查询,它使用 GROUP BY 和派生表,这两种方法都更有效。

    select Data1.country
     , Data1.manufacturer
     , Data1.category
     , Data1.month
     , Data1.year
     , Data1.Total
     , Data2.Total
    from (SELECT t1.country,
                 t1.manufacturer,
                 t1.category,
                 t1.month, 
                 t1.year,
                 SUM(value) 'Total'
            from data
            group by t1.country,
                     t1.manufacturer,
                     t1.category,
                     t1.month, 
                     t1.year) Data1
        inner join (SELECT country,
                           manufacturer,
                           category,
                           month, 
                           year,
                           SUM(value) 'Total'
                        from data
                        group by country,
                                 manufacturer,
                                 category,
                                 month, 
                                 year) Data2 on Data2.country = Data1.country
                                            and Data2.manufacturer = Data1.manufacturer
                                            and Data2.category = Data1.category
                                            and Data2.month = Data1.month
                                            and Data2.year = Data1.year -1
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2012-04-02
      • 2012-11-09
      • 1970-01-01
      • 2021-11-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多