SQL-“既不包含在聚合函数中,也不包含在GROUP BY子句中。”

时间:2018-10-18 09:14:42

标签: sql sql-server

使用SQL Server2016。我有一个表:

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子句显然出了问题,因为当我删除那个时,我得到了一个有效的结果。

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

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

任何帮助/指针都将不胜感激-我很亲密,但不能越过最后的关卡!

1 个答案:

答案 0 :(得分: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;

请注意,这会将“最后五天”解释为当前日期加上前四天。您的版本平均需要六天的时间。