DISTINCT и дубликаты: как найти двойников
Один и тот же отпечаток — на трёх карточках под тремя разными именами. Опечатка при вводе, смена псевдонима, повторная запись. Картотека не спрашивает, кого из трёх оставить, — это решаете вы.
DISTINCT — самый грубый инструмент: выбрасывает полные повторы, но не даёт выбора, какую версию оставить.
SELECT DISTINCT fingerprint_id
FROM registry;Сколько копий у одного отпечатка?
GROUP BY делает похожее, но пускает внутрь агрегаты — если помимо «оставить одного» нужно ещё что-то посчитать по группе.
SELECT fingerprint_id, COUNT(*) AS записей
FROM registry
GROUP BY fingerprint_id;«DISTINCT прячет двойников. Он не решает, кто из них настоящий. Он просто перестаёт их показывать.»
Выбрать конкретную версию — только ROW_NUMBER(): пронумеровать копии внутри своей группы по порядку и оставить первую.
WITH нумерация AS (
SELECT *,
ROW_NUMBER() OVER (PARTITION BY fingerprint_id ORDER BY updated_at DESC) AS rn
FROM registry
)
SELECT * FROM нумерация WHERE rn = 1;
-- ORDER BY DESC — оставляем самую свежую записьПочему DISTINCT спасает не всегда?
Капкан — тот же, что уже звучал: DISTINCT после кривого JOIN не лечит дубли, а маскирует их. Если после соединения строки размножились, правильный ход — разобраться с самим JOIN, а не спрятать симптом фильтром сверху.
«Замаскированный двойник хуже явного. Явного хотя бы видно.»
На работе так чистят базу перед аналитикой: оставляют последнюю запись на клиента, убирают повторные строки после неаккуратного импорта. Двойники не исчезают сами — их выбирают, кого оставить.
Двойники в архиве тоже есть. Кто из трёх настоящий, база не решит — это по-прежнему ваша работа.