SQL: вывод последнего пункта назначения каждого поезда
Быстрый ответ
Для извлечения записей с наиболее поздней датой в каждой группе можно использовать подзапрос или общее табличное выражение (CTE). Сперва определяем наибольшую дату для каждой группы, а затем соединяем полученный результат с исходной таблицей:
WITH RankedGroups AS (
SELECT *, ROW_NUMBER() OVER (PARTITION BY group_col ORDER BY date_col DESC) as rn
FROM my_table
)
SELECT *
FROM RankedGroups
WHERE rn = 1;
Пожалуйста, замените my_table
, group_col
и date_col
на реальные имена вашей таблицы и столбцов. Функция ROW_NUMBER()
присваивает уникальные номера строкам внутри групп, определённых по group_col
и упорядоченных по date_col
в порядке убывания, поэтому условие rn = 1
выбирает строки с самой поздней датой в каждой группе.
Использование подзапросов и обработка ошибок
С точки зрения производительности и для предотвращения ошибок подзапросы являются надёжным средством. Они помогают избежать распространенной ошибки, когда в GROUP BY
включаются столбцы без агрегации, тем самым предотвращая SQL-сбои:
SELECT mt.*
FROM my_table mt
INNER JOIN (
SELECT group_col, MAX(date_col) AS MaxDate
FROM my_table
GROUP BY group_col
) sub ON mt.group_col = sub.group_col AND mt.date_col = sub.MaxDate;
Освойте силу оконных функций
Не пропустите возможность использования оконных функций SQL, таких как RANK()
или DENSE_RANK()
, они смогут оказаться полезны в сложных случаях группировки и сортировки:
WITH RankedDestinations AS (
SELECT *, DENSE_RANK() OVER (PARTITION BY group_col ORDER BY date_col DESC) AS dest_rank
FROM my_table
)
SELECT *
FROM RankedDestinations
WHERE dest_rank = 1;
Сценарий из реальной жизни
Представьте выставку искусства, на которой художники представляют несколько работ:
| Художник | Даты выставок |
| -------- | ------------- |
| 🎨A | 1 янв, 5 янв, 10 янв |
| 🎨B | 2 янв, 3 янв, 9 янв |
Было бы замечательно увидеть только последние картины каждого художника:
SELECT Artist, MAX(Exhibition Dates)
GROUP BY Artist;
Таким образом, публика сможет оценить последние шедевры:
| 🎨 | Последний шедевр |
| -- | --------------- |
| A | 10 янв 🖼️ |
| B | 9 янв 🖼️ |
Теперь благодаря использованию GROUP BY с MAX(DATE) последние работы художников предстанут перед вниманием зрителей.
Мы легко справляемся со сложными ситуациями
Дуэль одинаковых дат
При наличии одинаковых максимальных дат можно установить приоритет, применив условия в функции ранжирования:
WITH RankedValues AS (
SELECT *,
ROW_NUMBER() OVER (
PARTITION BY group_col
ORDER BY date_col DESC, tiebreaker_col ASC
) AS rn
FROM my_table
)
SELECT *
FROM RankedValues
WHERE rn = 1;
Агент KEEP во власти
Для любителей элегантных SQL-решений, например в базе данных Oracle, пригодится функциональность KEEP
:
SELECT group_col,
MAX(date_col) KEEP (DENSE_RANK FIRST ORDER BY date_col DESC) AS LatestDate
FROM my_table
GROUP BY group_col;
Пусть этот трюк останется между нами, мастерами SQL. 😉
K.I.S.S (Коротко и ясно)
Сложные и длинные запросы всего лишь делают голову больной. Посмотрите на эту компактность записи:
SELECT mt.*, t.MaxDate
FROM my_table mt
JOIN LATERAL (
SELECT MAX(date_col) AS MaxDate
FROM my_table t1
WHERE mt.group_col = t1.group_col
) t ON mt.date_col = t.MaxDate;
Как известно, лаконичность – знак профессионализма.
Полезные материалы
- Недавние вопросы по теме 'sql+group-by+max' на Stack Overflow — Присоединяйтесь к SQL-сообществу для обсуждения 'GROUP BY' и 'MAX'.
- Обучающая статья по SQL GROUP BY на W3Schools — Пошаговые инструкции с понятными примерами.
- Основы SQL GROUP BY на Simple Talk — Освойте простые и сложные примеры использования GROUP BY с функциями MAX и MIN.
- SQLBolt – Урок 10: Запросы с агрегатами (Часть 1) — Изучите возможности GROUP BY и узнайте, как он работает в сочетании с HAVING и MAX(Date).
Завершение
Не прерывайте свои тренировки и совершенствуйте свое владение SQL. Чем больше практики — тем меньше ошибок. Поставьте лайк, если статья оказалась полезной, и помните о хорошем настроении. Всем успешного кодирования! 👩💻👨💻