关于GROUP BY的SQL问题

时间:2011-07-13 19:52:08

标签: sql

我已经使用SQL几年了,这种类型的问题出现了,我还没有找到答案。但也许我一直在寻找错误的地方 - 我不确定该怎么称呼它。

为了简洁起见,假设我有一个包含3列的表:Customer,Order_Amount,Order_Date。每个客户可能有多个订单,每个订单都有一行,包含金额和日期。

我的问题:SQL中是否有一种简单的方法可以获得每个客户的最大订单日期?

通过执行以下操作,我可以获得每个客户(以及由哪个客户制作)的最大订单金额:

SELECT Customer, MAX(Order_Amount) FROM orders GROUP BY Customer;

但我也想得到最大订单的日期,我还没想出一个容易获得的方法。我原以为这对于数据库来说是一种常见的问题,因此在SQL中很容易做到,但我还没有找到一种简单的方法。一旦我将Order_Date添加到要选择的列列表中,我需要将它添加到Group By子句中,我认为这不会给我我想要的内容。

7 个答案:

答案 0 :(得分:2)

没有捷径......最简单的方法可能就是加入一个子查询:

SELECT
    *
FROM
    orders JOIN
    (
        SELECT Customer, MAX(Order_Amount) AS Max_Order_Amount
        FROM orders 
        GROUP BY Customer
    ) maxOrder 
        ON maxOrder.Customer = orders.Customer 
        AND maxOrder.Max_Order_Amount = orders.Order_Amount

答案 1 :(得分:2)

你想要加入同一张桌子......

SELECT Customer, order_date, amt 
FROM orders o,
    ( SELECT Customer, MAX(Order_Amount) amt FROM orders GROUP BY Customer ) o2
WHERE o.customer = o2.customer
AND o.order_amount = o2.amt
;

答案 2 :(得分:2)

除了自我加入,你可以这样做:

SELECT o1.*
FROM orders o1 JOIN orders o2 ON o1.Customer = o2.Customer
GROUP BY o1.Customer, o1.Order_Amount
HAVING o1.Order_Amount = MAX(o2.Order_Amount);

有很好的article审查各种方法。

在Oracle,db2,Sybase,SQL Server 2005+中,您可以使用RANK() OVER

SELECT * FROM (
    SELECT *
    RANK() OVER (PARTITION BY Customer ORDER BY Order_Amount DESC) r
    FROM orders) o 
WHERE r = 1;

注意:如果Customer包含多个订单且最多Order_Amount(即关联),则使用RANK()函数可以获得所有此类订单;要获得第一个,请将RANK()替换为ROW_NUMBER()

答案 3 :(得分:1)

收集的另一种方法:

WITH tempquery AS 
(
    SELECT 
         Customer
        ,Order_Amount
        ,Order_Date
        ,row_number() OVER (PARTITION BY Customer ORDER BY Order_Amount DESC) AS rn
    FROM 
        orders 
)
SELECT 
     Customer
    ,Order_Amount
    ,Order_Date
FROM
    tempquery
WHERE
    rn = 1

答案 4 :(得分:1)

如果您的数据库支持CROSS APPLY,您也可以这样做,但它无法正确处理关系

SELECT [....]
FROM Customer c
CROSS APPLY 
(SELECT TOP 1 [...] 
 FROM Orders o
 WHERE c.customerID = o.CustomerID
 ORDER BY o.Order_Amount DESC) o

请参阅此data.SE query

答案 5 :(得分:0)

您可以尝试这样的事情:

SELECT Customer, MAX(Order_Amount), Order_Date 
FROM orders  O
WHERE ORDER_AMOUNT = (SELECT MAX(ORDER_AMOUNT) FROM orders WHERE CUSTOMER = O.CUSTOMER)
GROUP BY CUSTOMER, Order_Date 

答案 6 :(得分:0)

 with t as
(
 select  CUSTOMER,Order_Date ,Order_Amount,max(Order_Amount) over (partition 
 by Customer) as
 max_amount from orders
)
select * from t  where t.Order_Amount=max_amount