2009-12-10 172 views
11

我有了這個SQL查詢:如何在SQL查詢中選擇每個組的第一行?

SELECT Foo, Bar, SUM(Values) AS Sum 
FROM  SomeTable 
GROUP BY Foo, Bar 
ORDER BY Foo DESC, Sum DESC 

這導致類似這樣的輸出:

47 1 100 
47 0 10 
47 2 10 
46 0 100 
46 1 10 
46 2 10 
44 0 2 

我想只有每美孚第一行而忽略其他。

47 1 100 
46 0 100 
44 0 2 

我該怎麼做?

+0

好,什麼數據庫和什麼版本的你使用的是數據庫?這是一個很好的標籤候選人! – 2009-12-10 15:28:36

+0

選擇保存哪些記錄以及丟棄哪些記錄的標準是什麼? – nickf 2009-12-10 15:28:43

+0

@ILMV:有時候我希望你能給出好的編輯的重點...... – nickf 2009-12-10 15:29:22

回答

22
declare @sometable table (foo int, bar int, value int) 

insert into @sometable values (47, 1, 100) 
insert into @sometable values (47, 0, 10) 
insert into @sometable values (47, 2, 10) 
insert into @sometable values (46, 0, 100) 
insert into @sometable values (46, 1, 10) 
insert into @sometable values (46, 2, 10) 
insert into @sometable values (44, 0, 2) 

;WITH cte AS 
(
    SELECT Foo, Bar, SUM(value) AS SumValue, ROW_NUMBER() OVER(PARTITION BY Foo ORDER BY FOO DESC, SUM(value) DESC) AS RowNumber 
    FROM  @SomeTable 
    GROUP BY Foo, Bar 
) 
SELECT * 
FROM cte 
WHERE RowNumber = 1 
1

剛上Players.Nick組獨自一人,並選擇第一個(分)的說明

SELECT  Players.Nick, MIN(Reasons.Description), SUM(Marks.Value) AS Sum 
FROM   Marks INNER JOIN 
         Players ON Marks.PlayerID = Players.ID INNER JOIN 
         Reasons ON Marks.ReasonId = Reasons.ID 
GROUP BY Players.Nick 
ORDER BY Players.Nick, Sum DESC 

那就是如果你總是希望第一個不知道它

+0

我想要第三列中具有最高值的那一行。 – mafu 2009-12-10 15:51:07

0

(編輯編輯過的問題的基礎) 然後,因爲您希望根據聚合列的值進行過濾,所以您需要的是Having Clause。

SELECT p.Nick, r.Description, SUM(m.Value) Sum 
    FROM Marks m 
    JOIN Players p 
     ON m.PlayerID = p.ID 
    JOIN Reasons r 
     ON m.ReasonId = r.ID 
    GROUP BY p.Nick, r.Description 
    Having SUM(m.Value) = 
     (Select Max(Sum) From 
     (SELECT SUM(m.Value) Sum 
     FROM Marks mi 
      JOIN Players pi 
       ON mi.PlayerID = pi.ID 
      JOIN Reasons r i 
      ON mi.ReasonId = ri.ID 
     Where pi.Nick = p.Nick 
     GROUP BY pi.Nick, ri.Description)) 

    Order By p.Nick, Sum Desc 
+0

我不想通過'X'選擇輸出。取而代之的是第三行的值(見編輯)。 – mafu 2009-12-10 15:47:15

0

通常,嘗試使用子查詢而不是加入和分組 - 它通常會使SQL更容易理解。

SELECT Nick, 
    (SELECT Description from Reasons WHERE Reasons.ID = (
     SELECT FIRST(Marks.ReasonId) from Marks WHERE Marks.PlayerID = Players.ID) 
    ), 
    (SELECT SUM(Value) from Marks WHERE Marks.PlayerID = Players.ID) 
0

這是一個使用'HAVING'條款的機會嗎? (你想歧視一個聚合函數 - '總和')?

+0

我這麼認爲。它會是什麼樣子? – mafu 2009-12-10 15:56:40

2

我可能會不同意rjmunru的看法,因爲使用Ansii風格的聯接通常比子查詢更容易閱讀,但是對於他自己 - 我只是按照我們的DBA說的做。

如果你只是想要查詢的第一個結果,你可能會使用rownum(如果使用oracle,其他數據庫可能有類似的東西)。

SELECT * FROM foo_t˚F 其中f.bar = '的Bleh' 和ROWNUM = 1

當然HAVING子句也可能是合適的,這取決於你正在嘗試做。

「HAVING用於對由GROUP BY創建的組執行操作,類似於基本SQL語句中的WHERE子句。WHERE子句限制評估的行.HAVING子句限制返回的分組行。 「

hth

+0

如果我理解正確,那麼這就是我想要的,實際上。 – mafu 2009-12-10 15:58:27

0

好奇。只有這樣,我才能解決這個問題,就是在內存中使用一個臨時保存表。 (TSQL語法)

-- original test data 
declare @sometable table (foo int, bar int, value int) 

insert into @sometable values (1, 5, 10) 
insert into @sometable values (1, 4, 20) 
insert into @sometable values (2, 1, 1) 
insert into @sometable values (2, 1, 10) 
insert into @sometable values (2, 1, 1) 
insert into @sometable values (2, 2, 13) 
insert into @sometable values (3, 4, 25) 
insert into @sometable values (3, 5, 1) 
insert into @sometable values (3, 1, 1) 
insert into @sometable values (3, 1, 1) 
insert into @sometable values (3, 1, 1) 
insert into @sometable values (3, 1, 1) 
insert into @sometable values (3, 1, 1) 

-- temp table for initial aggregation 
declare @t2 table (foo int, bar int, sums int) 
insert into @t2 
select foo, bar, sum(value) 
from @sometable 
group by foo, bar 

-- final result 
select foo, bar, sums 
from @t2 a 
where sums = 
    (select max(sums) from @t2 b 
    where b.foo = a.foo) 
0

SQL Server 2005中您可以使用此:

聲明@sometable表(FOO INT,酒吧INT,值INT)

INSERT INTO @sometable值(1,插入到@sometable值(2,1,10) 插入到@sometable值(1,4,20) 插入到@sometable值(2,1,1) 插入到@sometable值2,1,1) 插入@sometable值(2,2,13)插入到@sometable值(3,4,25) 插入到@sometable值(3,5,1) 插入到@sometable值(3,1,1) 插入到@sometable值(3, 1) INSERT INTO @sometable值(3,1,1) INSERT INTO @sometable值(3,1,1) INSERT INTO @sometable值(3,1,1)

- 臨時表爲初始聚合 DECLARE @ T2表(INT FOO,棒INT,求和INT) 插入到由富從@sometable 組@ T2 選擇FOO,棒,和(值) ,酒吧

SELECT * FROM(SELECT FOO,酒吧,求和,ROW_NUMBER()OVER(PARTITION BY富ORDER BY和的降序)ROWNO FROM @ T2)x,其中x.ROWNO = 1

1

這是一箇舊帖子,但今天我有同樣的問題。我已經通過嘗試許多查詢來解決它,直到它工作。我正在使用Visual Basic 2010中的SQL Compact 3.5。

本示例針對名爲「TESTMAX」的表,其中包含列「Id」(主鍵),「nom」(名稱)和「value」,您可以使用此獲得具有最大的「價值」行每個「NOM」:

SELECT TESTMAX.Id, TESTMAX.NOM, TESTMAX.Value 
FROM  TESTMAX INNER JOIN 
        TESTMAX AS TESTMAX_1 ON TESTMAX.NOM = TESTMAX_1.NOM 
WHERE (TESTMAX.Value IN 
         (SELECT MAX(Value) AS Expr1 
         FROM  TESTMAX AS TESTMAX_2 
         WHERE (NOM = TESTMAX_1.NOM))) 
GROUP BY TESTMAX.Id, TESTMAX.NOM, TESTMAX.Value 

如果你想刪除其他行,你也可以使用:

DELETE FROM TESTMAX 
WHERE (Id NOT IN 
         (SELECT TESTMAX_3.Id 
         FROM  TESTMAX AS TESTMAX_3 INNER JOIN 
             TESTMAX AS TESTMAX_1 ON TESTMAX_3.NOM = TESTMAX_1.NOM 
         WHERE (TESTMAX_3.Value IN 
              (SELECT MAX(Value) AS Expr1 
               FROM  TESTMAX AS TESTMAX_2 
               WHERE (NOM = TESTMAX_1.NOM))) 
         GROUP BY TESTMAX_3.Id, TESTMAX_3.NOM, TESTMAX_3.Value)) 
相關問題