Проблема с множественной группировкой. Как получить одну строку из группы?

#sql #sql-server #sql-server-2008 #sql-server-2012 #greatest-n-per-group

#sql #sql-сервер #sql-server-2008 #sql-server-2012 #наибольшее число на группу

Вопрос:

Это таблица с моими данными:

 -----------------------------
|   date   |  value  |  id  |
|03/05/18  |5        | 1    |
|03/05/18  |3        | 2    |
|03/05/18  |5        | 3    |
|03/05/18  |6        | 4    |
|03/05/18  |9        | 5    |
|08/03/19  |5        | 6    |
|08/03/19  |3        | 7    |
|08/03/19  |1        | 8    |
|08/03/19  |6        | 9    |
|01/06/20  |7        | 10   |
|01/06/20  |0        | 11   |
|01/06/20  |2        | 12   |
-----------------------------
  

Мне нужно найти максимальное значение в каждой дате и вывести его с соответствующим идентификатором.
Пример:

 -----------------------------
|   date   |  value  |  id  |
|03/05/18  |9        | 5    |
|08/03/19  |6        | 9    |
|01/06/20  |7        | 10   |
-----------------------------
  

Теперь я знаю, как вывести максимальное значение в каждой дате, но без соответствующего идентификатора.
Пример:

 ----------------------
|   date   |  value  |
|03/05/18  |9        |
|08/03/19  |6        |
|01/06/20  |7        |
----------------------
  

Программное обеспечение, которое я использую, — MS SQL Server 2012.

Мой код:

     SELECT 
    date,
    MIN(value)
    
    FROM 
    my_table
    
    GROUP BY date
  

Я пробовал функцию SQL Server «FIRST_VALUE«, но это не помогло.

ТАКЖЕ я попытался создать условие сравнения в подзапросе и столкнулся с некоторыми проблемами с указанием переменных (псевдонимов) снаружи и внутри моего подзапроса.

Есть идеи, пожалуйста?

Комментарии:

1. Вычислите row_number() over (partition by date order by value desc) as rn в CTE, а затем отфильтруйте rn = 1

2. @dnoeth, спасибо! Я сделал это 🙂

Ответ №1:

Вы можете фильтровать с помощью подзапроса:

 select t.*
from mytable t
where t.value = (select max(t1.value) from mytable t1 where t1.date = t.date)
  

Это позволило бы связать верхние строки, если таковые имеются. Другой вариант — использовать оконные функции:

 select *
from (
    select t.*, rank() over(partition by date order by value desc) rn
    from mytable t
) t
where rn = 1
  

Если вы хотите разорвать связи, вы можете использовать row_number() вместо rank() — но для получения стабильного результата вам понадобится второй столбец в order by предложении.

Комментарии:

1. Спасибо за ваш ответ! Я пробовал оба метода, но получаю странные результаты. Моя таблица не была отфильтрована. В поле значение у меня есть только константа для всех записей

2. Какой тип данных для вашего поля с именем ‘value’?