【问题标题】:Find rows with all columns duplicated and no unique field in PostgreSQL在 PostgreSQL 中查找所有列重复且没有唯一字段的行
【发布时间】:2021-08-06 06:50:07
【问题描述】:

假设我有一个这样的表,其中没有任何列或列组合可以保证是唯一的:

GAME_EVENT USERNAME ITEM QUANTITY
sell poringLUVR sword 1
sell poringLUVR sword 1
kill daenerys civilians 200000
kill daenerys civilians 200000
invoke sylvanas undead 1000000

我想检索多次存在的所有行的列表(其中所有列的组合出现多次)。

(在这种情况下,我希望得到一个包含“sell/poringLUVR”和“kill/daenerys”行的列表)

解决这个问题的好方法是什么?合并索引会有帮助吗?也欢迎对非 Postgres 方法提出建议。

【问题讨论】:

  • 您的实际表定义总是有助于解决任何此类问题(会告诉我们NOT NULL 约束等)。并且始终是您的 Postgres 版本。

标签: sql postgresql indexing duplicates postgresql-performance


【解决方案1】:

假设所有列 NOT NULL,这将是:

SELECT *
FROM   tbl t1
WHERE  EXISTS (
   SELECT FROM tbl t2
   WHERE  (t1.*) = (t2.*)
   AND    t1.ctid <> t2.ctid
   );

ctid is a system column,“元组标识符”/“项目指针”可以在没有实际 PK(您显然没有)的情况下用作穷人的 PK,并且只能在单个的范围内询问。相关:

如果列可以是NULL,(更昂贵)使用IS NOT DISTINCT FROM 而不是=。见:

(t1.*) = (t2.*) 正在比较 ROW 值。这个较短的语法是等效的:t1 = t2 除非基础表中存在同名的列,在这种情况下,第二种形式失败,而第一种形式不会。见:

索引?

如果任何列具有特别高的基数(许多不同的值,很少重复),我们将其称为 hi_cardi_column 就本答案而言,仅在该列上的普通 btree 索引可以有效地完成您的任务。几个小列与多列索引的组合也可以工作。关键是要有一个小而快的索引,否则开销就不会支付。

SELECT *
FROM   tbl t1
WHERE  EXISTS (
   SELECT FROM tbl t2
   WHERE  t1.hi_cardi_column = t2.hi_cardi_column -- logically redundant
   AND    (t1.*) = (t2.*)
   AND    t1.ctid <> t2.ctid
   );

添加的条件t1.hi_cardi_column = t2.hi_cardi_column在逻辑上是多余的,但有助于利用所述索引。

除此之外,我认为索引支持的潜力不大,因为无论如何都必须访问表的所有行,并且必须检查所有列。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2023-03-16
    • 2018-02-02
    • 2021-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-11-13
    • 2015-07-05
    相关资源
    最近更新 更多