我可以限制GROUP BY语句中用于组的行数

时间:2009-09-17 21:17:40

标签: sql group-by

我有一个奇怪的问题

我有一个包含product_id,sales和day

列的表格

并非所有产品每天都有销售。我想获得每个产品在过去10天内销售的平均销售数量

通常我会得到像这样的平均值

SELECT product_id, AVG(sales) 
FROM table 
GROUP BY product_id

有没有办法限制每种产品要考虑的行数?

我担心这是不可能的,但我想检查某人是否有想法

更新以澄清:

产品可在第1,3,5,10,15,17,20天出售。 因为我不想得到所有日子的平均值,而只想得到产品实际销售的平均日期

SELECT product_id, AVG(sales) 
FROM table 
WHERE day > '01/01/2009' 
GROUP BY product_id

不起作用

4 个答案:

答案 0 :(得分:1)

如果您想要产品销售的最后10个日历日:

SELECT product_id, AVG(sales)
FROM table t
JOIN (
   SELECT product_id, MAX(sales_date) as max_sales_date
   FROM table
   GROUP BY product_id
) t_max ON t.product_id = t_max.product_id 
  AND  DATEDIFF(day, t.sales_date, t_max.max_sales_date) < 10
GROUP BY product_id;

日期差异是SQL Server特定的,您必须将其替换为日期差异功能的服务器语法。

要获得产品销售的最后10天:

SELECT product_id, AVG(sales)
FROM (
    SELECT product_id, sales, DENSE_RANK() OVER 
           (PARTITION BY product_id ORDER BY sales_date DESC) AS rn
    FROM Table
) As t_rn
WHERE rn <= 10
GROUP BY product_id;

这假设sales_date是日期,而不是日期时间。如果字段是日期时间,则必须提取日期部分。

最后一个窗口函数免费版本:

SELECT product_id, AVG(sales)
FROM Table t
WHERE sales_date IN (
 SELECT TOP(10) sales_date 
 FROM Table s
 WHERE t.product_id = s.product_id
 ORDER BY sales_date DESC)
GROUP BY product_id;

同样,sales_date被认为是日期,而不是日期时间。如果您的服务器没有支持TOP,请使用其他限制语法。

答案 1 :(得分:0)

给它一个旋转。子查询选择有销售的产品的最后十天,外部查询进行聚合。

SELECT t1.product_id, SUM(t1.sales) / COUNT(t1.*) 
FROM table t1
   INNER JOIN (
               SELECT TOP 10 day, Product_ID
               FROM table t2
               WHERE (t2.product_ID=t1.Product_ID)
               ORDER BY DAY DESC 
               ) 
   ON (t2.day=t1.day) 

GROUP BY t1.product_id
BTW:这种方法使用correlated subquery,这可能不是很有效,但它应该在理论上有效。

答案 2 :(得分:0)

我不确定我是否做得对,但如果你想获得过去10天产品的平均销售量,你可以按照以下步骤进行:

SELECT Product_Id,Sum(Sales)/Count(*) FROM (SELECT ProductId,Sales FROM Table WHERE SaleDAte>=@Date) table GROUP BY Product_id HAVING Count(*)>0

或者您可以使用更容易的AVG Aggregate功能:

SELECT Product_Id,AVG(Sales) FROM (SELECT ProductId,Sales FROM Table WHERE SaleDAte>=@Date) table GROUP BY Product_id

<强>更新

现在我得到了你的意思,据我所知,在一个查询中不可能这样做。如果我们可以做这样的事情(Northwind数据库),这是可能的:

select a.CustomerId,count(a.OrderId) 
from Orders a INNER JOIN(SELECT CustomerId,OrderDate FROM Orders Order By OrderDate) AS b ON a.CustomerId=b.CustomerId GROUP BY a.CustomerId Having count(a.OrderId)<10

但你不能在子查询中使用order by,除非你使用不适合这种情况的TOP。但是你可以这样做:

SELECT PorductId,Sales INTO #temp FROM table Order By Day

    select a.ProductId,Sum(a.Sales) /Count(a.Sales)
    from table a INNER JOIN #temp AS b ON a.ProductId=b.ProductId GROUP BY a.ProductId Having count(a.Sales)<=10

答案 3 :(得分:0)

如果这是一个销售交易表,那么在没有销售的日子里就不应该有任何行。即,如果ProductId 21在6月1日没有销售,那么这个表不应该有任何行productId = 21和day ='1 June'...因此你不应该过滤任何东西 - 不应该有任何东西到过滤掉

Select ProductId, Avg(Sales) AvgSales
From Table 
Group By ProductId

应该可以正常工作。所以,如果不是,那么你没有完全或准确地解释问题。

此外,在您的问题中,您在示例SQL查询中显示平均值(销售额),但在文本中您提到“每个产品的平均销售数量......”您是否需要平均销售额或平均值销售交易数量?您是否希望仅按产品的平均值(即每种产品报告一个输出值)或者您是否想要每天每件产品的平均值?

如果您想要单独使用每件产品的平均值,那么在此之前的十天内只需销售一次?或每件产品最后一次销售日期前十天? 如果后者那么

Select ProductId, Avg(Sales) AvgSales
From Table T
Where day > (Select Max(Day) - 10
             From Table
             Where ProductId = T.ProductID)
Group By ProductId

如果您想要单独的每件产品的平均值,对于每个产品的最后一次销售日期之前的十天 销售 的那些销售,那么< / p>

Select ProductId, Avg(Sales) AvgSales
From Table T
Where (Select Count(Distinct day) From Table
       Where ProductId = T.ProductID
          And Day > T.Day) <= 10
Group By ProductId