Что делает SQL-запрос?
Что проверяют
Умеете ли вы читать чужой запрос вслух: что он вернёт, по каким строкам сгруппирует, где потеряет данные. На месте такого вопроса обычно лежит распечатка конкретного запроса, и от аналитика ждут не пересказа синтаксиса, а разбора результата.
Как отвечать
Разбирайте по порядку логической обработки, а не по порядку написания:
fromи соединения формируют исходный набор строк;whereотсекает строки до группировки;group byсхлопывает строки в группы;havingфильтрует уже группы, по агрегатам;selectвычисляет выражения и оконные функции;order byиlimitработают последними.
Эта последовательность отвечает почти на все уточняющие вопросы: почему псевдоним из select нельзя использовать в where, почему условие по count идёт в having, почему оконная функция не видна фильтру.
select user_id, count(*) as events
from events
where created_at >= current_date - interval '7 days'
group by user_id
having count(*) > 10
order by events desc
limit 50;Читая вслух, называйте не только результат, но и места, где он сломается: соединение, размножившее строки, испортит count; условие по колонке с NULL молча выбросит строки; count(column) и count(*) считают разное.
Где спотыкаются
Пересказывают синтаксис вместо результата: «здесь select, здесь where». Интервьюер ждёт фразу вида «вернёт по строке на пользователя за последнюю неделю, только для тех, у кого больше десяти событий».
Второе: не замечают, что соединение до группировки размножило строки. count(*) после соединения с таблицей, где на пользователя приходится несколько записей, считает пары, а не события. Лечится это через count(distinct ...) или предварительной агрегацией в подзапросе.
Третье: забывают про NULL. Условие на неравенство не вернёт строки, где значение не заполнено, а sum по пустой группе даёт NULL, а не ноль.