Я работаю над каталогом продуктов (электронная торговля), хранящимся в базе данных PostgreSQL. В настоящее время у меня есть дубликаты. Я хотел бы удалить эти дублированные продукты, оставив только самый дешевый.
Поля в базе данных, которые важны:
ID [PK] SKU EAN Price ....
1 SKU1 123 45.0 ....
2 SKU2 456 36.0 ....
3 SKU3 123 40.0 ....
4 SKU4 789 58.0 ....
5 SKU5 123 38.0 ....
...
У меня есть SERIAL PRIMARY KEY в поле ID. У меня есть NOT NULL SKU, NOT NULL код EAN-13 и NOT NULL цена для каждого продукта.
Мы видим, что EAN "123" дублируется несколько раз. Я хотел бы найти SQL-запрос, который удаляет все дубликаты (всю строку), оставляя только ОДИН, который будет иметь самую низкую цену.
Мы бы хотели иметь :
ID [PK] SKU EAN Price ....
2 SKU2 456 36.0 ....
4 SKU4 789 58.0 ....
5 SKU5 123 38.0 ....
...
Чтобы знать: количество дубликатов может быть переменным. Вот пример с 3 продуктами с одинаковым EAN, но у нас может быть 2, 4, 8 или 587...
До сих пор мне удавалось удалить дубликат с самым низким или самым большим идентификатором только в случае двух дубликатов, но это не то, что я пытаюсь найти...
FROM
(SELECT Price,
MIN(Price) OVER( PARTITION BY ean ORDER BY Price DESC ) AS row_num FROM TABLE ) t
WHERE t.row_num > 1 );
Вот одно решение, использующее синтаксис Postgres DELETE ... USING
:
DELETE
FROM mytable t1
USING mytable t2
WHERE t1.sku = t2.sku AND t1.price > t2.price
Это удалит записи с дубликатами sku
, сохранив запись с наименьшим price
.
Я бы сделал это, используя коррелированный подзапрос:
delete from mytable t
where t.price > (select min(t2.price) from mytable t2 where t2.sku = t.sku);
Разве не должно быть
Price ASC
? Таким образом, самый дешевый будет иметь row_number, равный1
.