Выберите максимальное значение для каждого (Col1, Col2)
Предположим, что следующая таблица:
Name SubName Message Time
USA MA M1 1
USA NY M2 2
USA WA M3 3
USA MA M4 4
USA WA M5 5
USA NY M6 6
FIN HEL M7 7
FIN TAM M8 8
FIN HEL M9 9
Мне нужен SQL-запрос, который вернет следующее:
Name SubName Message Time
FIN HEL M9 9
FIN TAM M8 8
USA NY M6 6
USA WA M5 5
USA MA M4 4
поэтому a ORDER BY time DESC
, который сгруппирован по разному имени и подгруппирован под отдельным именем.
Возможно ли это? Я ищу решение, которое не является специфичным для СУБД - что-то, что может работать в большинстве СУБД.
Ответы
Ответ 1
Вы не отметили свои РСУБД, поэтому для ANSI-SQL
, который должен работать на большинстве СУБД, вы можете использовать ROW_NUMBER()
:
SELECT s.* FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.name,t.subname ORDER BY t.time DESC) as rnk
FROM YourTable
) s
WHERE s.rnk = 1
ORDER BY s.time DESC,s.name
EDIT: Вот ответ с Core ANSI SQL, который должен работать с ЛЮБОЙ базой данных, вы можете использовать NOT EXISTS()
:
SELECT * FROM YourTable t
WHERE NOT EXISTS(SELECT 1 FROM YourTable s
WHERE t.name = s.name and t.subname = s.subname
AND s.time > t.time)
Ответ 2
SELECT * FROM
#TEMP T1 WHERE TIME=
(SELECT MAX(TIME) FROM #TEMP T2
WHERE T1.NAME=T2.NAME AND T2.SUBNAME=T1.SUBNAME)
Выход:
Name SubName Message Time
USA WA M5 5
USA NY M6 6
USA MA M4 4
FIN TAM M8 8
FIN HEl M9 9
Ответ 3
И если ваши dbms не поддерживают расширение ANSI SQL T611, Элементарные операции OLAP:
select t1.*
from tablename t1
join (select name, subname, max(Time) maxtime
from tablename
group by name, subname)
on t1.name = t2.name and
t1.subname = t2.subname and
t1.time= t2.maxtime
order by name, subname, time desc
Используется следующая функция вне Core SQL-2003: F591, "Производные таблицы"
Обратите внимание, что ANSI SQL имеет time
как зарезервированное слово, поэтому вам может потребоваться разграничить его как "time"
.
Ответ 4
Вы можете сделать это в два этапа. Сначала выберите лучшее для каждой комбинации name
/subname
. Затем закажите их. В большинстве баз данных вы можете использовать row_number()
для первой части:
select t.*
from (select t.*,
row_number() over (partition by t.name, t.subname order by time desc) as seqnum
from t
) t
order by time desc;
Ответ 5
может использовать ROW_NUMBER() и WHERE s.rank = 1
, чтобы получить первую запись в каждой группе, сделанную разделом:
SELECT s.Name,s.SubName,s.Message, s.Time
FROM (
SELECT t.*,
ROW_NUMBER() OVER(PARTITION BY t.Name, t.SubName ORDER BY t.Time DESC) as rank
FROM YourTable t) s
WHERE s.rank = 1
ORDER BY s.Time DESC
Ответ 6
Я не тестировал это, но думаю, что это должно работать:
select
t1.name as name,
t1.subname as subname,
(select max(t2.message) from table t2 where t2.name = t1.name and t2.subname = t1.subname) as message,
(select max(t2.time) from table t2 where t2.name = t1.name and t2.subname = t1.subname) as time
from
table t1
group by
t1.name,
t1.subname
order by
t1.name