簡體   English   中英

如何 select SQL 查詢中每組的第一行?

[英]How do I select the first row per group in an SQL Query?

我有這個 SQL 查詢:

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

這導致 output 與此類似:

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

我只想每個 Foo 的第一行(它和它的最高 Bar),並忽略 rest。

47  1   100
46  0   100
44  0   2

我怎么做?

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

我可能不同意rjmunru,因為使用Ansii樣式連接通常比子查詢更容易閱讀,但對於他自己的每個 - 我只是按照我們的DBA所說的去做。

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

select * from foo_t f其中f.bar ='bleh'和rownum = 1

當然,HAVING子句也可能是合適的,具體取決於您要做的事情。

“HAVING用於對GROUP BY創建的組執行類似於基本SQL語句中行的WHERE子句的操作.WHERE子句限制計算的行.HAVING子句限制返回的分組行。”

心連心

只需將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

那就是如果你總是想要第一個不知道它

這是一個老帖子,但今天我遇到了同樣的問題。 我通過嘗試許多查詢來解決它,直到它工作。 我正在使用SQL Compact 3.5和visual basic 2010。

此示例適用於名為“TESTMAX”的表,其中包含“Id”(主鍵),“nom”(名稱)和“value”列,您可以使用此示例獲取每個“nom”的最大“value”行:

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))

(已編輯基於已編輯的問題)然后,由於您希望根據聚合列的值進行過濾,因此您需要的是具有條款。

  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

通常,嘗試使用子查詢而不是連接和分組 - 它通常使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)

這是使用'HAVING'條款的機會嗎? (你想區分聚合函數 - 'Sum')?

好奇。 只有這樣才能讓它工作才能在內存中使用臨時保存表。 (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)

SQL Server 2005你可以使用這個:

聲明@sometable表(foo int,bar int,value int)

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

- 用於初始聚合的臨時表聲明@t2表(foo int,bar int,sums int)插入@ t2選擇foo,bar,來自@sometable group的sum(value)by foo,bar

select * from(SELECT foo,bar,sums,ROW_NUMBER()OVER(PAROTION BY Foo ORDER BY Sums DESC)ROWNO from @ t2)x其中x.ROWNO = 1

暫無
暫無

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

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