分组的SQL子查询问题,平均

Posted

技术标签:

【中文标题】分组的SQL子查询问题,平均【英文标题】:SQL sub-query problem with grouping, average 【发布时间】:2008-09-30 15:35:34 【问题描述】:

在 MS Transact SQL 中,假设我有一个像这样的表(订单):

 Order Date       Order Total     Customer #
 09/30/2008       8.00            1
 09/15/2008       6.00            1
 09/01/2008       9.50            1
 09/01/2008       1.45            2
 09/16/2008       4.50            2
 09/17/2008       8.75            3
 09/18/2008       2.50            3

我需要的是:对于每个客户,最近两个订单的平均订单金额。所以对于客户 #1,我应该得到 7.00(而不是 7.83)。

我已经盯着这个看了一个小时(在一个更大的问题中,我已经解决了),我认为我的大脑已经冻结了。帮助解决一个简单的问题?

【问题讨论】:

一个客户一天可以有多份订单吗? 【参考方案1】:

这应该成功了

select avg(total), customer 
from orders o1 
where orderdate in 
  ( select top 2 date 
    from orders o2 
    where o2.customer = o1.customer 
    order by date desc )
group by customer

【讨论】:

如果在某一天有超过 1 个订单,例如如果对于客户,您一天有 3 个订单。子查询将为您提供 2 条同一日期的记录,顶部查询将考虑所有 3 条订单 - 但也许这不是上下文中的真实场景。 在现实生活中,日期列也会存储时间,所以不会有问题 如果您的 OrderDate 仅具有“日分辨率”,您还可以针对记录的 CreatedDate 上的 TOP 2。如果您有 CreatedDate,那就是。 ;-) 如果你没有,那么你没有获得最后两次销售所需的数据,所以你的数据架构是错误的 实际上,此表的真实版本存在分辨率问题(日期,但不是时间),但对于我需要的信息来说已经足够接近了。【参考方案2】:

在 SQL Server 2005 中,您有 RANK 函数,与分区一起使用:

USE AdventureWorks;
GO
SELECT i.ProductID, p.Name, i.LocationID, i.Quantity
    ,RANK() OVER 
    (PARTITION BY i.LocationID ORDER BY i.Quantity DESC) AS 'RANK'
FROM Production.ProductInventory i 
    INNER JOIN Production.Product p 
        ON i.ProductID = p.ProductID
ORDER BY p.Name;
GO

Link

【讨论】:

这有点矫枉过正。在性能方面,这样做有充分的理由吗? 就?必须有一个该死的很好的理由来转移标准 SQL 的几行代码就可以得到相同的结果。 Microsoft 提供了一个函数(RANK with PARTITION)来处理此类情况。功能越具体,执行计划就越好。所以恕我直言,它在未来的可读性和性能方面都更好。 如果有多个标准来定义“排名”和分区,排名方法会更简单、更清晰。有关排名使查询更简单的示例,请参见 /questions/150891/sql-query-remove-duplicates-with-caveats#151410【参考方案3】:

一种选择是让您使用光标遍历所有客户 ID,然后将平均值作为几个子查询。

不过,请注意,对于大型数据集,查询效率不高,可能需要很长时间才能处理。

【讨论】:

以上是关于分组的SQL子查询问题,平均的主要内容,如果未能解决你的问题,请参考以下文章

SQL语句汇总——聚合函数分组子查询及组合查询

oracle 分组查询 子查询 统计查询 FROM加子查询临时表 查询高于平均工资 示例代码

一文让你彻底理解SQL关联子查询

SQL语句汇总(三)——聚合函数分组子查询及组合查询 - Darly

使用子查询和分组依据每天计算每个国家/地区的 DAU 平均值

sql子查询可以再分组吗