#sql #oracle #group-by
#sql #Oracle #группировка по
Вопрос:
У меня есть таблица с тремя столбцами (id, col2, col3, col4), где col2 — это A или B, а col3 и col4 — целые числа. Моя проблема в том, что есть много столбцов с одинаковым идентификатором и другим значением col2, и я хочу выбрать ТОЛЬКО те строки, которые имеют максимальное значение в col3.
Например, если у нас есть:
id | col2 | col3 | col4
1 | A | 3 | 2
1 | B | 5 | 3
2 | A | 6 | 2
...
Я хочу сохранить только кортеж (1, B, 5, 3). Как я могу этого добиться?
Я пробовал это:
SELECT id, col2, MAX(col3), col4 FROM t GROUP BY id;
но я получаю сообщение об ошибке, в котором говорится, что это недопустимый оператор GROUP BY .
Комментарии:
1. Когда вы говорите «сохранить только …» — что вы имеете в виду под этим? Вы хотите
delete
строки из таблицы? Или вы просто имеете в виду в отчете (технически, вselect
инструкции SQL)? Две разные интерпретации очень разные. Затем, если у вас есть несколько строк для одного идентификатора, но две или более (или даже все из них) имеют одинаковое наибольшее значениеcol3
, что вы хотите сохранить? ВСЕ эти строки (с максимальным значением вcol3
)? Или только одну из них — и тогда, какую?
Ответ №1:
Вы можете использовать keep
:
SELECT id,
MAX(col2) KEEP (DENSE_RANK FIRST ORDER BY col3 DESC) as col2
MAX(col3),
MAX(col4) KEEP (DENSE_RANK FIRST ORDER BY col3 DESC) as col4
FROM t
GROUP BY id;
Или:
SELECT id, col2, col3, col4
FROM (SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY id ORDER BY col3 DESC) as seqnum
FROM t
) t
WHERE seqnum = 1;
Ответ №2:
Этот запрос:
select t.*
from tablename t inner join (
select id, max(col3) col3
from tablename
group by id
having count(distinct col2) > 1
) g on g.id = t.id and g.col3 = t.col3
возвращает для каждого id
, который имеет разные значения col2
только в 1 строке: тот, который содержит максимальное значение col3
.
Если вам также нужны другие строки, в которых каждая id
из них не имеет разных значений col2
, тогда используйте UNION ALL
:
select t.*
from tablename t inner join (
select id, max(col3) col3
from tablename
group by id
having count(distinct col2) > 1
) g on g.id = t.id and g.col3 = t.col3
union all
select t.* from tablename t
where not exists (
select 1 from tablename
where id = t.id and col2 <> t.col2
)
Ответ №3:
выберите * из TableName где col3 = (выберите max(col3) из TableName)