Как фильтровать только актуальные данные в SQL запросе
Что проверяют
Понимаете ли вы, что «актуальные» каждый раз определяется заново: последняя версия записи, действующая на дату, неудалённая или за последний период. Интервьюер ждёт, что вы сначала уточните смысл, а потом покажете оконную функцию. Следом обычно спрашивают, что будет при одинаковых updated_at.
Как отвечать
Разложите на типовые случаи:
- последняя версия на ключ:
ROW_NUMBER() OVER (PARTITION BY order_id ORDER BY updated_at DESC)в подзапросе и фильтрrn = 1. В Snowflake, BigQuery и Databricks то же пишется короче черезQUALIFY, в PostgreSQL черезDISTINCT ON (order_id) ... ORDER BY order_id, updated_at DESC, в ClickHouse черезargMax,LIMIT 1 BYилиReplacingMergeTreeсFINAL; - SCD2-измерение: текущая версия это
valid_to IS NULLили флагis_current, а состояние на датуdберётся условиемvalid_from <= d AND (valid_to > d OR valid_to IS NULL); - мягкое удаление:
deleted_at IS NULLилиis_active = true, и этот фильтр нужен в каждом джойне, а не только в основной таблице; - окно по времени: полуоткрытый интервал
ts >= '2026-09-01' AND ts < '2026-09-02', а неBETWEEN. Заодно проговорите часовой пояс: сутки по UTC и по Москве это разные строки.
Про скорость: по ключу разбиения и полю сортировки нужен индекс или подходящая сортировка в таблице (ORDER BY в MergeTree, кластеризация в облачном хранилище). Если текущее состояние запрашивают часто, его выгоднее материализовать в отдельную таблицу или витрину, чем каждый раз гонять окно по всей истории.
Где спотыкаются
Берут MAX(updated_at) с GROUP BY и джойнят обратно к таблице. При двух записях с одинаковой меткой времени ключ задваивается. У ROW_NUMBER та же ловушка в другом виде: без второго ключа сортировки, например id, результат недетерминирован.
Пишут BETWEEN '2026-09-01' AND '2026-09-30' по колонке с временем и теряют почти весь последний день: правая граница означает полночь.
Кладут условие на правую таблицу LEFT JOIN в WHERE. Строки без пары отфильтровываются, и левый джойн молча превращается во внутренний; условие должно стоять в ON.