Sobes.tech
Назад к вопросам
Middle
11

Как фильтровать только актуальные данные в SQL запросе?

Компании, где спрашивали
AvitoAvito

Ответ от нейросети

sobes.tech AI

Что хотят услышать интервьюеры:

Нужно уметь отделять «текущую» запись от истории изменений. Обычно для этого используют признак актуальности, дату окончания действия или оконные функции. Важно показать, что фильтрация зависит от модели хранения данных, а не от одного универсального SQL-приёма.

Определение:

Актуальные данные — это записи, которые считаются действующими на момент запроса. Чаще всего это означает, что запись имеет признак is_current = 1, либо у неё нет даты завершения (end_date IS NULL), либо она имеет самый свежий updated_at/версию среди дублей.

Способ фильтрации выбирают в зависимости от схемы:

  • если есть флаг актуальности — фильтруют по нему;
  • если есть период действия — проверяют текущую дату в диапазоне;
  • если есть история версий — выбирают последнюю запись по ключу объекта;
  • если нужна одна запись на сущность — используют ROW_NUMBER() или MAX() в подзапросе.

Пример использования:

-- Вариант 1: есть флаг актуальности
SELECT *
FROM customers
WHERE is_current = 1;

-- Вариант 2: есть период действия
SELECT *
FROM prices
WHERE CURRENT_DATE BETWEEN valid_from AND COALESCE(valid_to, CURRENT_DATE);

-- Вариант 3: нужно выбрать последнюю версию по клиенту
WITH ranked AS (
    SELECT
        c.*,
        ROW_NUMBER() OVER (
            PARTITION BY customer_id
            ORDER BY updated_at DESC
        ) AS rn
    FROM customer_history c
)
SELECT *
FROM ranked
WHERE rn = 1;

Пояснение кода:

В первом запросе выбираются только строки, помеченные как текущие через is_current = 1. Это самый простой и быстрый вариант, если флаг поддерживается корректно.

Во втором запросе актуальность определяется временем действия записи. CURRENT_DATE BETWEEN valid_from AND COALESCE(valid_to, CURRENT_DATE) оставляет только те строки, для которых текущая дата попадает в период действия. COALESCE помогает обработать открытый интервал, если дата окончания не заполнена.

В третьем запросе используется оконная функция ROW_NUMBER(). Она нумерует версии внутри каждого customer_id по убыванию updated_at, и rn = 1 оставляет только самую свежую запись.

Если кода нет, логика всё равно одна: сначала определить правило актуальности в модели данных, затем применить соответствующий фильтр.

Ключевые моменты:

  • Способ фильтрации зависит от того, как в таблице хранится история.
  • Самые частые варианты: флаг актуальности, период действия, последняя версия записи.
  • Для выбора одной строки на сущность удобно использовать ROW_NUMBER() OVER (PARTITION BY ...).
  • При фильтрации по датам важно учитывать границы интервала и NULL в поле окончания.
  • Для больших таблиц лучше, чтобы поля фильтрации были индексированы.
  • Если данные поступают из DWH/ELT-процессов, актуальность часто определяется витриной, а не исходной таблицей.