【问题标题】:Enforcing uniqueness on PostgreSQL table column after non-unique values already inserted在已插入非唯一值后强制 PostgreSQL 表列的唯一性
【发布时间】:2011-03-18 19:19:57
【问题描述】:

我已经有 8000 万条记录插入到一​​个表中,但需要确保一些列是共同唯一的。但是,这些列已经包含非唯一数据,因此 ALTER TABLE 不起作用。

我想要一个查询,它可以让我轻松删除非唯一记录,同时保留其中一个,或者一个允许我在过滤的同时将当前表中的数据加载到新表中的查询为了独特性。

【问题讨论】:

  • 当这些列的唯一性被违反时,您是否有一个标准来选择保留哪一行以及丢弃哪一行?
  • 是的,一个日期列。我会保留最近的记录。如果由于某种原因这些也是重复的,那么任何一个都可以。

标签: sql postgresql unique duplicates


【解决方案1】:

您要查找的查询是:

select distinct on (my_unique_1, my_unique_2) * from my_table;

这将为distinct on 中的每个列组合选择一行。实际上,它始终是第一行。没有order by 很少使用它,因为没有可靠的行返回顺序(所以这是第一个)。

结合order by,您可以选择哪些行是第一行(这会留下具有最​​大 last_update_date 的行):

 select distinct on (my_unique_1, my_unique_2) * 
 from my_table order by my_unique_1, my_unique_2, last_update_date desc;

现在您可以将其选择到新表中:

 create table my_new_table as
 select distinct on (my_unique_1, my_unique_2) * 
 from my_table order by my_unique_1, my_unique_2, last_update_date desc;

或者你可以用它来删除,假设row_id是一个主键:

 delete from my_table where row_id not in (
     select distinct on (my_unique_1, my_unique_2) row_id 
     from my_table order by my_unique_1, my_unique_2, last_update_date desc);

【讨论】:

  • 关于“第一行”:如果没有 ORDER BY,就无法判断哪一行会先返回,因此“第一行”是一个误导性术语,因为您可能并不总是得到同样的结果。如果没有 ORDER BY 子句,DISTINCT ON 几乎没有用处。
  • 我读到了 distinct,但我也尝试将它与 Limit 1000 一起使用,只是为了检查输出。花了很长时间,但我认为那是因为我必须暂时删除索引才能快速插入更多数据。感谢您提供清晰的示例,但我对distinct on 之后的my_unique 列感到困惑。文档说这些应该是表达式,那么将列包含为表达式是否只是确保它们存在于记录中?我问是因为我实际上需要确保这些列不仅存在,而且共同唯一。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2015-04-17
  • 2023-03-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2014-06-20
  • 2011-12-24
相关资源
最近更新 更多