分组的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子查询问题,平均的主要内容,如果未能解决你的问题,请参考以下文章
oracle 分组查询 子查询 统计查询 FROM加子查询临时表 查询高于平均工资 示例代码
SQL语句汇总(三)——聚合函数分组子查询及组合查询 - Darly