簡體   English   中英

如何選擇SUM()+ Group By后的最大值?

[英]How do I select the max value after a SUM() + Group By?

幾天后我在大學里進行了一次SQL期末考試,我的查詢讓我發瘋了! 我知道這是一個愚蠢的問題,但我剛剛開始,無法搞清楚。

所以,有基本的2個表,客戶端和訂單。

     Client           Orders
     ---------        ---------
 PK  Client_Id    PK  Order_Id
     Name             Client_Id   FK
                      Order_Total
                      Date

現在,他們要我“列出2011年購買量最大的客戶名稱”

因此,對於我的想法,這需要一方面,我從2011年開始全部按Order_Total和Group by Client,然后從該表中選擇具有MAX()總和的客戶端,然后僅顯示名稱那個客戶。 問題是我無法弄清楚如何將所有這些放在一個查詢中。

希望有人可以幫忙!


謝謝大家的快速回復! 我真的很感動!

現在,我並不是說挑剔或任何東西,但為了防止我的老師不接受“限制”或“選擇頂部”聲明,有沒有辦法在沒有這些的情況下進行此查詢?

編輯:從注釋移植的原始代碼嘗試:

SELECT 
  C.NAME
FROM 
  CLIENTS C,
  ORDERS O 
WHERE 
  O.CLIENT_ID = C.CLIENT_ID 
  AND O.DATE BETWEEN '1/1/2011 00:00:00.000' and '12/31/2011 23:59:59.999' 
HAVING SUM(O.ORDER_TOTAL) >= ALL (SELECT SUM (O2.ORDER_TOTAL) FROM ORDER O2 GROUP BY O2.CLIENT_ID)
SELECT T.X
 (SELECT C.NAME X, SUM(O.ORDER_TOTAL)
 FROM CLIENT C, ORDERS O
 WHERE C.CLIENT_ID = O.CLIENT_ID
   AND YEAR(O.DATE) = 2011
 GROUP BY O.CLIENT_ID
 ORDER BY 2 DESC
 LIMIT 1) T;

有很多方法可以給這只貓上皮......這就是我通常會這樣做的方法:

select top 1 c.Client_Id, c.Name, o.Order_Total
from Client c
join (select Client_Id, SUM(Order_Total) as Order_Total
      from Orders 
      where `Date` between '1/1/2011 00:00:00.000' and '12/31/2011 23:59:59.999'
      group by Client_Id) o
  on c.Client_Id = o.Client_Id
order by o.Order_Total desc

基本上你是拉動訂單總數列表,加入反對,按順序排序降序,並將查詢限制為1個結果。

根據你的問題,Is7aq的答案是正確的,但只適用於MySQL。 盡管我承認這不是原始問題中列出的約束,但它也沒有考慮到一個以上客戶在特定年份購買量最大的可能性。 一旦數據庫變得足夠大,通過簡單地使用逗號來交叉連接也是一個巨大的性能損失,因此使用INNER或OUTER連接幾乎總是更好,並指定連接的條件。 無論如何,這是一個練習,這就是我所擁有的。 它可能可以更好地優化:

   CREATE TABLE #Client (
     Client_Id int not null,
     Name varchar(100) not null
   )

   INSERT INTO #Client VALUES (1, 'Client 1')
   INSERT INTO #Client VALUES (2, 'Client 2')
   INSERT INTO #Client VALUES (3, 'Client 3')

   CREATE TABLE #Orders (
     Order_Id int not null,
     Client_Id int not null,
     Order_Total int not null,
     Date datetime not null
   )

   -- Customer 1: total=105
   INSERT INTO #Orders VALUES (1, 1, 55, '1/1/2011')
   INSERT INTO #Orders VALUES (2, 1, 50, '1/1/2011')
   INSERT INTO #Orders VALUES (3, 1, 45, '1/1/2010') -- test removal of invalid dates

   -- Customer 2: total=120
   INSERT INTO #Orders VALUES (4, 2, 40, '1/1/2011')
   INSERT INTO #Orders VALUES (5, 2, 40, '1/1/2011')
   INSERT INTO #Orders VALUES (6, 2, 40, '1/1/2011')

   -- Customer 3: total=120
   INSERT INTO #Orders VALUES (7, 3, 40, '1/1/2011')
   INSERT INTO #Orders VALUES (8, 3, 40, '1/1/2011')
   INSERT INTO #Orders VALUES (9, 3, 40, '1/1/2011')

   -- control customer to test hi/lo scenarios: total=40
   INSERT INTO #Orders VALUES (10, 4, 10, '1/1/2011')
   INSERT INTO #Orders VALUES (11, 4, 10, '1/1/2011')
   INSERT INTO #Orders VALUES (12, 4, 10, '1/1/2011')
   INSERT INTO #Orders VALUES (13, 4, 10, '1/1/2011')

   SELECT T.NAME, 
          T.OrderTotal
     FROM (SELECT C.NAME, 
                  SUM(O.ORDER_TOTAL) OrderTotal
             FROM #CLIENT C
            INNER JOIN #ORDERS O
               ON c.CLIENT_ID = o.CLIENT_ID
            WHERE YEAR(O.DATE) = 2011
         GROUP BY C.NAME) as T
     WHERE T.OrderTotal = (SELECT MAX(T2.OrderTotal2)
                             FROM (SELECT C2.NAME, 
                                          SUM(O2.ORDER_TOTAL) OrderTotal2
                                     FROM #CLIENT C2
                               INNER JOIN #ORDERS O2
                                       ON c2.CLIENT_ID = o2.CLIENT_ID
                                    WHERE YEAR(O2.DATE) = 2011
                                 GROUP BY C2.NAME) as T2) 
  GROUP BY T.Name, T.OrderTotal

  DROP TABLE #Client
  DROP TABLE #Orders

  -- Output
  -- Client 2: 120
  -- Client 3: 120
SELECT Client.Name
FROM Client LEFT JOIN Orders ON Orders.Client_Id = Client.Client_Id
WHERE YEAR(Orders.Date) = 2011
GROUP BY Client.Client_Id
ORDER BY SUM(Order.Order_Total) DESC
LIMIT 1

你幾乎就在那里,你只需要從你的聚合查詢中進行選擇。 它被稱為派生表。

所以你有這個:

select c.client_id, c.name, sum(order_total) ordersum
from client c 
inner join orders o on c.client_id = o.client_id
where year(o.date) = 2011
group by c.client_id, c.name

這給了你你的金額。 現在你想要第一個。 有幾種方法可以做到這一點,它還取決於你正在使用的DBMS(mysql,mssql等)。最簡單的方法是:

select top 1 *
from (
select c.client_id, c.name, sum(order_total) ordersum
from client c 
inner join orders o on c.client_id = o.client_id
where year(o.date) = 2011
group by c.client_id, c.name
) a
order by ordersum desc

在給定的平台上可能會有一些更簡單的東西,但該查詢應該足夠通用,可以處理您正在使用的任何DBMS。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM