【问题标题】:conditionally remove duplicates from database in postgres有条件地从 postgres 中的数据库中删除重复项
【发布时间】:2020-10-11 16:30:18
【问题描述】:

我想从“值”列中删除重复项,但前提是与之前的更新相比没有变化。我阅读了有关滞后和领先的教程,但找不到删除重复项的示例。

原文:

+----+-------+-------+------------------------+
| ID | subID | value |       updated_at       |
+----+-------+-------+------------------------+
|  1 |     2 | 2.20  | 2020-02-16 07:36:25+01 |
|  1 |     2 | 2.20  | 2020-02-16 07:31:25+01 |
|  1 |     2 | 2.20  | 2020-02-16 07:26:25+01 |
|  1 |     2 | 2.30  | 2020-02-16 07:21:25+01 |
|  1 |     2 | 2.20  | 2020-02-16 07:16:25+01 |
|  1 |     2 | 2.20  | 2020-02-16 07:11:25+01 |
+----+-------+-------+------------------------+

期望的输出:

+----+-------+-------+------------------------+
| ID | subID | value |       updated_at       |
+----+-------+-------+------------------------+
|  1 |     2 | 2.20  | 2020-02-16 07:36:25+01 |
|  1 |     2 | 2.30  | 2020-02-16 07:21:25+01 |
|  1 |     2 | 2.20  | 2020-02-16 07:16:25+01 | 
+----+-------+-------+------------------------+

【问题讨论】:

  • 您的 ID/subid 与我期望的 ID 不同!所有重复项是怎么回事?

标签: database postgresql select window-functions gaps-and-islands


【解决方案1】:

这是一个孤岛问题。如果你想在每个值改变之前的最后一行,你可以使用lead()

select *
from (
    select 
        t.*, 
        lead(value) over(partition by id, sub_id order by updated_at) next_value
    from mytable t
) t
where value <> next_value or next_value is null

另一方面,如果您想在每次值更改后使用第一个值,则可以使用 lag() 而不是 lead()(查询的其余部分应保持不变)。

【讨论】:

    【解决方案2】:

    我会使用滞后或领先并通过 ctid 删除:

    DELETE FROM yourtable WHERE ctid IN
    (
      SELECT
        ctid
      FROM 
      (
        SELECT 
          ctid,
          value,
          LAG(value) OVER(PARTITION BY id, subid ORDER BY updated_at) pre
        FROM 
          yourtable t
      ) t
      WHERE value = pre 
    )
    

    与来自 Internet 的任何删除查询一样,针对表的副本运行它...

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2016-09-27
      • 1970-01-01
      • 2015-05-16
      • 2021-01-23
      • 2018-02-05
      • 2018-02-17
      • 2020-05-22
      • 1970-01-01
      相关资源
      最近更新 更多