Как выбрать первую строку для каждой группы в SQL Query?
У меня есть этот 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
Я хотел бы иметь только первую строку на Foo и игнорировать остальные.
47 1 100
46 0 100
44 0 2
Как это сделать?
Ответы
Ответ 1
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
Ответ 2
Я мог бы не согласиться с rjmunru тем, что использование сочетаний стиля Ansii часто может быть легче читать, чем подзапросы, но для каждого из них - я просто следую тому, что говорят наши администраторы баз данных.
Если вам нужен только первый результат запроса, вы можете использовать rownum (если использовать oracle, другие базы данных, вероятно, имеют что-то похожее).
выберите * из foo_t f
где f.bar = 'bleh' и rownum = 1
Конечно, предложение HAVING также может быть соответствующим, в зависимости от того, что вы пытаетесь сделать.
"HAVING используется для выполнения действия над группами, созданными GROUP BY, аналогичными действиям WHERE в строках в базовом выражении SQL. Предложение WHERE ограничивает оцениваемые строки. Предложение HAVING ограничивает возвращаемые сгруппированные строки".
HTH
Ответ 3
Просто установите группу на 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
если вы всегда хотите первого, не зная об этом
Ответ 4
Это старая должность, но сегодня у меня была такая же проблема. Я решил это, попробовав много запросов, пока это не сработает. Я использую SQL Compact 3.5 с визуальным базовым 2010.
Этот пример предназначен для таблицы с именем "TESTMAX" с столбцами "Id" (первичный ключ), "nom" (имя) и "значение", вы можете использовать это для получения строк с максимальным значением для каждого "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))
Ответ 5
(EDITED На основании отредактированного вопроса)
Затем, поскольку вы хотите отфильтровать, основываясь на значении агрегированного столбца, вам понадобится параметр "Бытие".
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
Ответ 6
В общем, попробуйте использовать подзапросы, а не присоединяться и группировать - это часто делает 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)
Ответ 7
Возможно ли использовать предложение "HAVING"? (Вы хотите различить по агрегатной функции - "Сумма" )?
Ответ 8
Любопытный. Единственный способ, которым я мог заставить это работать, - использовать временную таблицу хранения в памяти.
(Синтаксис 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)
Ответ 9
SQL Server 2005 вы можете использовать это:
объявить @sometable table (foo int, bar int, значение int)
вставить в значения @sometable (1, 5, 10)
вставлять в значения @sometable (1, 4, 20)
вставлять в значения @sometable (2, 1, 1)
вставлять в значения @sometable (2, 1, 10)
вставлять в значения @sometable (2, 1, 1)
вставлять в значения @sometable (2, 2, 13)
вставлять в значения @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)
- временная таблица для начальной агрегации
declare @t2 table (foo int, bar int, sums int)
вставить в @t2
выберите foo, bar, sum (value)
из @sometable
group by foo, bar
выберите * from (
SELECT foo, bar, sums, ROW_NUMBER() OVER (PARTITION by Foo ORDER BY Sums DESC) ROWNO
FROM @t2) x где x.ROWNO = 1