Выделите клиентов с несколькими различными email, пронумеруйте их записи от новых к старым и удалите строки с номером больше 1.
Есть таблица t:
Выделите клиентов с несколькими различными email, пронумеруйте их записи от новых к старым и удалите строки с номером больше 1.
Короткий ответ
Что ответить на собеседовании
Подробный разбор
Ответ с пояснениями
Условие
Есть таблица t:
| id | id_client | create_date | |
|---|---|---|---|
| 1 | 1 | [phone]T10:00:00.000Z | [email] |
| 2 | 1 | [phone]T11:00:00.000Z | [email] |
| 3 | 2 | [phone]T08:00:00.000Z | [email] |
| 4 | 2 | [phone]T10:00:00.000Z | [email] |
| 5 | 2 | [phone]T11:00:00.000Z | [email] |
| 6 | 3 | [phone]T08:00:00.000Z | [email] |
| 7 | 3 | [phone]T09:00:00.000Z | [email] |
| 8 | 4 | [phone]T12:00:00.000Z | [email] |
| 9 | 4 | [phone]T13:00:00.000Z | [email] |
| 10 | 5 | [phone]T14:00:00.000Z | [email] |
| 11 | 5 | [phone]T15:00:00.000Z | [email] |
Нужно проверить, есть ли в таблице клиенты с несколькими email. Если есть, то удалить их (оставить только последнюю запись по create_date).
Ответ
Выделите клиентов с несколькими различными email, пронумеруйте их записи от новых к старым и удалите строки с номером больше 1.
Пример для PostgreSQL; id предполагается уникальным, id_client — непустым. COUNT DISTINCT не учитывает NULL в email.
WITH multi AS (
SELECT id_client
FROM t
GROUP BY id_client
HAVING COUNT(DISTINCT email) > 1
), ranked AS (
SELECT t.id,
ROW_NUMBER() OVER (
PARTITION BY t.id_client
ORDER BY t.create_date DESC NULLS LAST, t.id DESC
) AS rn
FROM t
JOIN multi USING (id_client)
)
DELETE FROM t
USING ranked r
WHERE t.id = r.id AND r.rn > 1;
При одинаковом времени выбирается запись с большим id. Сначала проверьте удаляемые id через SELECT и выполняйте изменение контролируемо в транзакции. В условии даты и адреса скрыты, поэтому перечислить конкретные удаляемые строки невозможно, но алгоритм от этого не меняется.