我的表格结构如下:
id | foodid | ingredientid
我想创建一个唯一索引,如下所示:
create unique index foodingredient_foodid_ingredientid_uindex
on foodingredient (foodid, ingredientid);
问题是该表包含大量重复的 foodid 和做什么成分。这些是不必要的,我想删除它们。
如果我跑步:
select count(*)
from foodingredient
group by foodid, ingredientid
having count(*) > 1
order by count desc
这将返回 50 万行。因此,手动修复这些问题不是一个选择。
所以我想做的是删除所有重复项,同时保留原始内容。
即
id | foodid | ingredientid
1 | 144 | 531
2 | 144 | 531
3 | 144 | 531
4 | 144 | 531
变成:
id | foodid | ingredientid
1 | 144 | 531
有没有办法通过查询来做到这一点?
你可以用存在来做到这一点:
delete from foodingredient t
where exists (
select 1 from foodingredient
where foodid = t.foodid and ingredientid = t.ingredientid and id < t.id
)
查看演示。
DELETE FROM foodingredient a
USING foodingredient b
WHERE a.id > b.id
AND a.foodid = b.foodid
AND a.ingredientid = b.ingredientid;
您也可以仅选择不同的行并使用它们来创建新表。
简单选择只是为了看看发生了什么。
SELECT DISTINCT ON (foodid, ingredientid) id, foodid, ingredientid
FROM foodingredient LIMIT 100
从上面的 SELECT 创建新表。
CREATE TABLE foodingredient_uniq AS select * FROM (
SELECT DISTINCT ON(foodid, ingredientid) id, foodid, ingredientid
FROM foodingredient
)
如果您想按 id 排序新表,那么还要添加 ORDER BY
CREATE TABLE foodingredient_uniq AS select * FROM (
SELECT DISTINCT ON(foodid, ingredientid) id, foodid, ingredientid
FROM foodingredient
) t1 ORDER BY t1.id
然后删除旧表并将 foodingredient_uniq 重命名为 foodingredient。对于非常大的表,它比上面的自连接解决方案要快得多。在我自己的用例中,24 小时 vs 20 分钟,具有 200M 行表和约 30% 的唯一行。