2

Неочевидные факты про MIN и MAX

Серия SQL: знакомство

Простые функции. Кажется, что они находят просто минимум и максимум. Но есть и особенность их использования для интерпретации результатов. Об этом далее.

Неочевидные факты про MIN и MAX

А пока подписывайся на мой канал На связи: SQL Там я публикую посты про особенности и нюансы SQL. Этот канал про то, как не бояться баз данных, понимать, что такое JOIN, GROUP BY и почему NULL ≠ 0. Его я веду с нуля подписчиков. Присоединяйся!

MIN и MAX — не только про числа

Они работают с любыми типами данных:

  • датами (MIN(date) даст самую раннюю дату),

  • строками (MAX(name) вернёт последнюю в алфавитном порядке),

  • булевыми значениями (MIN(bool) — false, MAX(bool) — true).

Иногда этим можно ловко воспользоваться — например, чтобы узнать, есть ли хоть один true:

SELECT MAX(is_active) FROM users;

Если вернёт true — значит, кто-то активен. Красиво и лаконично.

MIN и MAX — не только агрегатные, но и оконные функции

Можно получить минимум или максимум в рамках окна, не теряя детализацию:

SELECT

user_id,

date,

MAX(date) OVER (PARTITION BY user_id) AS last_activity

FROM logins;

Так можно легко вытащить, когда пользователь последний раз заходил — без группировки и без JOIN.

MIN/MAX и NULL

Они игнорируют NULL.
То есть если у тебя все значения NULL, то результат — NULL.
Это часто ломает аналитику, особенно при сравнении с COALESCE или при объединении данных.

SELECT MAX(COALESCE(score, 0)) -- вернёт 0, а не NULL

→ Иногда важно явно заменить NULL, чтобы не получить "пустой" результат.

MIN/MAX могут ускорить выборку

Если в таблице есть индекс по нужному полю —
MIN() и MAX() используют только крайний элемент индекса.
Это значит, что:

SELECT MAX(price) FROM products;

может пройтись не по миллиону строк, а просто взять последнее значение из B-tree индекса.
То есть — мгновенно.

Можно найти строку с минимальным/максимальным значением

Классическая боль аналитика: как вытащить не просто максимум, а всю строку, где он встретился.

💡 Один из лучших способов — оконная функция + фильтр:

SELECT *

FROM (

SELECT *,

ROW_NUMBER() OVER (ORDER BY salary DESC) AS rn

FROM employees

) t

WHERE rn = 1;

→ Получаем сотрудника с максимальной зарплатой.
Без подзапросов, без JOIN, без боли.

Неочевидный кейс: поиск экстремумов в группах

SELECT department, MIN(salary), MAX(salary)

FROM employees

GROUP BY department;

Классика, но важно:
разница между MAX и MIN = разброс значений, полезный показатель в аналитике (например, зарплат).

💬 Если хочешь больше таких разборов с реальными кейсами SQL без воды — подписывайся на мой Telegram 👉На связи: SQL
Там я рассказываю про SQL так, чтобы стало интересно даже тем, кто раньше его ненавидел 😄

Автор поста оценил этот комментарий

В данном случае, так же как и в

вытащить не просто максимум, а всю строку, где он встретился

явно эффективней использовать всё же специально для этого предназначенный DISTINCT ON, а вовсе не оконные функции.

Можете сравнить планы запросов, если не верите.


А если хотелось показать именно оконные функции, то там куда интересней LEAD/LAG. Если уже MIN/MAX, то, для начала, с FILTER ( WHERE ... ) и только потом оконные и полностью, с RANGE/ROWS/GROUPS. Без последнего от оконных функций толку мало.

раскрыть ветку (1)
0
Автор поста оценил этот комментарий

Спасибо за идею, возможно в следующих постах будет тема: DISTINCT ON vs ROW_NUMBER ...
DISTINCT ON - для PostgreSQL, ROW_NUMBER - стандартный SQL, В MySQL, Oracle, SQL Server - вроде бы такого синтаксиса нет.

5
Автор поста оценил этот комментарий

SELECT MAX(is_active) FROM users;

Если вернёт true — значит, кто-то активен. Красиво и лаконично.

Не красиво и не лаконично. Во-первых, например, в PostgreSQL функции MAX и MIN не применимы к типу данных boolean.

Во-вторых, в этих случаях не зачем делать агрегацию. Намного эффективней

SELECT is_active FROM users WHERE is_active LIMIT 1;



SELECT

user_id,

date,

MAX(date) OVER (PARTITION BY user_id) AS last_activity

FROM logins;

Так можно легко вытащить, когда пользователь последний раз заходил — без группировки и без JOIN.

Но при этом будет столько строк, сколько каждый пользователь заходил. Зачем гнать лишние строки с сервера на клиента, если можно сделать так:

SELECT DISTINCT ON (user_id) user_id, date AS last_activity

FROM logins

ORDER BY user_id, date DESC;


подписывайся на мой Telegram

После такого, не рекомендую подписываться.

раскрыть ветку (1)
Автор поста оценил этот комментарий

в PostgreSQL функции MAX и MIN не применимы к типу данных boolean.



Спасибо за внимательность. В документации действительно тип boolean не задокументирован.
У меня почему-то "упорядоченность " взяло вверх для этого примера.



SELECT

user_id,

date,

MAX(date) OVER (PARTITION BY user_id) AS last_activity

FROM logins;


Но при этом будет столько строк, сколько каждый пользователь заходил. Зачем гнать лишние строки с сервера на клиента

SELECT DISTINCT ON (user_id) user_id, date AS last_activity

FROM logins

ORDER BY user_id, date DESC;

Дальнейшая аналитика тут не прослеживается и задача не заканчивается, на выявлении последней даты входа. Это просто один из способов с использованием оконных функций.

показать ответы

Темы

Политика

Теги

Популярные авторы

Сообщества

18+

Теги

Популярные авторы

Сообщества

Игры

Теги

Популярные авторы

Сообщества

Юмор

Теги

Популярные авторы

Сообщества

Отношения

Теги

Популярные авторы

Сообщества

Здоровье

Теги

Популярные авторы

Сообщества

Путешествия

Теги

Популярные авторы

Сообщества

Спорт

Теги

Популярные авторы

Сообщества

Хобби

Теги

Популярные авторы

Сообщества

Сервис

Теги

Популярные авторы

Сообщества

Природа

Теги

Популярные авторы

Сообщества

Бизнес

Теги

Популярные авторы

Сообщества

Транспорт

Теги

Популярные авторы

Сообщества

Общение

Теги

Популярные авторы

Сообщества

Юриспруденция

Теги

Популярные авторы

Сообщества

Наука

Теги

Популярные авторы

Сообщества

IT

Теги

Популярные авторы

Сообщества

Животные

Теги

Популярные авторы

Сообщества

Кино и сериалы

Теги

Популярные авторы

Сообщества

Экономика

Теги

Популярные авторы

Сообщества

Кулинария

Теги

Популярные авторы

Сообщества

История

Теги

Популярные авторы

Сообщества

Недвижимость и ремонт

Теги

Популярные авторы

Сообщества