Как подходить к решению SQL задачи?
Что проверяют
Для data scientist и ML-инженера SQL это способ собрать датасет, и интервьюер смотрит, думаете ли вы о корректности выборки, а не только о синтаксисе. Типовая задача: посчитать признаки или метрику по событиям пользователей. Следом спрашивают, как не допустить утечки данных из будущего и что делать, если запрос на большой таблице работает час.
Как отвечать
- зерно и срез времени: сначала определите, что такое одна строка будущей выборки, например пользователь на дату прогноза. Все признаки считаются только по событиям до этой даты, иначе модель на обучении видит будущее;
- проверка ключей: перед соединением убедитесь, что ключ в справочнике уникален. Сравнение
COUNT(*)иCOUNT(DISTINCT key)за секунду показывает, размножатся ли строки; - оконные функции:
ROW_NUMBER() OVER (PARTITION BY user_id ORDER BY ts DESC)для последнего события,LAG()для интервалов между событиями, скользящие суммы черезROWS BETWEEN. Фильтр по результату окна делается во внешнем запросе или черезQUALIFYтам, где он есть (Snowflake, BigQuery, DuckDB); - условная агрегация:
COUNT(*) FILTER (WHERE ...)в PostgreSQL илиSUM(CASE WHEN ... THEN 1 ELSE 0 END)в любом диалекте, чтобы посчитать десяток признаков за один проход; - производительность:
EXPLAINилиEXPLAIN ANALYZE, фильтр по партиции и дате как можно раньше, чтение только нужных колонок, особенно в колоночных хранилищах вроде ClickHouse и BigQuery. Для разведки подходят приближённые функции, напримерAPPROX_COUNT_DISTINCTв BigQuery и Spark SQL, и работа на части данных; - сверка: итоговое число строк, доля NULL в признаках, распределение таргета. Эти проверки лучше закрепить в пайплайне.
Где спотыкаются
Считают признаки по всей истории пользователя, включая период после целевого события. Метрики на валидации отличные, в проде модель проваливается.
Делают JOIN с таблицей, где ключ не уникален, и получают дубли объектов в обучающей выборке. Модель подстраивается под повторённые строки, а число строк никто не сверил.
Заменяют NULL нулём не глядя. Для модели «нет данных» и «ноль покупок» это разные сигналы, и их лучше разделять отдельным флагом.