Короткий ответ
Оконная функция ROW_NUMBER() присваивает номер каждой версии события. Сортировка по времени получения по убыванию делает последнюю запись первой.
Как это работает подробнее
Дедупликацию безопаснее выполнять в очищенной модели, не удаляя raw-слой. Если нужна физическая очистка, сначала сохраните резервную копию и используйте устойчивый первичный ключ строки.
- Ключ группы. Обычно это
event_id, иногда вместе сsource. - Порядок. При одинаковом
received_atнужен уникальный tie-breaker, напримерingestion_id.
Пример кода
deduplicate_events.sql
WITH ranked AS (
SELECT events_raw.*,
ROW_NUMBER() OVER (
PARTITION BY source, event_id
ORDER BY received_at DESC, ingestion_id DESC
) AS row_num
FROM events_raw
)
SELECT *
FROM ranked
WHERE row_num = 1;Что использовать на практике
- Сравните число строк результата с числом уникальных ключей дедупликации.
- Зафиксируйте правило выбора победившей версии и контролируйте долю дублей во времени.
Подводные камни
- Недетерминированная сортировка. При равном времени результат может меняться между запусками.
- DISTINCT по всем полям. Он не объединит копии с разным техническим временем получения.