【问题标题】:SQL - "not contained in either an aggregate function or the GROUP BY clause."SQL - “不包含在聚合函数或 GROUP BY 子句中。”
【发布时间】:2018-10-18 09:14:41
【问题描述】:

使用 SQL Server 2016。我有一张表:

Product   Qty   OrderDate
--------------------------
Toys      100   2018-10-01
Toys      100   2018-10-01
Books      30   2018-10-01
Toys      150   2018-10-02
Toys       50   2018-10-02
Toys       20   2018-10-02
Toys      110   2018-10-03
Toys       90   2018-10-04
Toys      200   2018-10-05
Toys      100   2018-10-05
Toys       30   2018-10-08
Toys       50   2018-10-09

我想计算过去 5 天每件产品的平均数量。我很接近这个查询:

SELECT 
  Product,
  RowNumber, 
  OrderDate, 
  AVG(TotalQty) OVER (ORDER BY RowNumber DESC ROWS 5 PRECEDING) as RollingAvg
FROM 
(
SELECT ROW_NUMBER() OVER (PARTITION BY Product ORDER BY orderDate) AS RowNumber, Product, OrderDate, sum(Qty) as TotalQty
  FROM Tbl 
  GROUP BY Product, OrderDate
) x
GROUP BY Product, RowNumber, OrderDate

内部查询正常工作,为我提供每个产品/日期对的总数。但是我的外部查询报告了一个问题:

Column 'x.TotalQty' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause.

显然我的 OVER 子句有问题,因为当我删除 that 时,我得到了一个有效的结果。

语法上有效的查询(做错事):

SELECT 
  Product,
  RowNumber, 
  OrderDate, 
  AVG(TotalQty) as RollingAvg
FROM 
(
SELECT ROW_NUMBER() OVER (PARTITION BY Product ORDER BY orderDate) AS RowNumber, Product, OrderDate, sum(Qty) as TotalQty
  FROM Tbl 
  GROUP BY Product, OrderDate
) x
GROUP BY Product, RowNumber, OrderDate

任何帮助/指针将不胜感激 - 我很接近,但无法跨越这最后的障碍!

【问题讨论】:

  • 用你给定的样本数据,你能告诉我们想要的输出吗? ...只是为了确保我们理解问题。
  • 在您的第一个查询中,您可以简单地删除group by。由于您使用的是窗口函数,因此不需要 group by

标签: sql sql-server


【解决方案1】:

我想你想要:

SELECT Product, RowNumber, OrderDate, 
       AVG(TotalQty) OVER (ORDER BY RowNumber DESC ROWS 5 PRECEDING) as RollingAvg
FROM (SELECT ROW_NUMBER() OVER (PARTITION BY Product ORDER BY orderDate) AS RowNumber,
             Product, OrderDate, sum(Qty) as TotalQty
      FROM Tbl 
      GROUP BY Product, OrderDate
     ) x;

也就是说,外部聚合是不必要的,因为AVG() 被用作窗口函数,而不是聚合函数。

你应该能够在没有子查询的情况下做到这一点:

SELECT ROW_NUMBER() OVER (PARTITION BY Product ORDER BY orderDate) AS RowNumber,
       Product, OrderDate, sum(Qty) as TotalQty,
       AVG(SUM(Qty)) OVER (PARTITION BY Product ORDER BY orderDate ROWS BETWEEN 4 PRECEDING AND CURRENT ROW) as avg_5
FROM Tbl 
GROUP BY Product, OrderDate;

请注意,这会将“过去五天”解释为当天加上前四天。您的版本平均有六天。

【讨论】:

  • 这已经解决了 - 谢谢!我还想要 ORDER BY RowNumber ASC(不是 DESC),但这是一个相对较小的修复。
猜你喜欢
  • 2022-01-14
  • 1970-01-01
  • 2013-02-10
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2012-12-07
  • 2013-08-31
相关资源
最近更新 更多