Если две строки имеют одинаковый идентификатор, но разные col2, как вы можете сохранить только те, которые имеют max col3?

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