2009-12-10 140 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))