【问题标题】:PostgreSQL with-delete "relation does not exists"PostgreSQL with-delete “关系不存在”
【发布时间】:2017-12-05 18:59:20
【问题描述】:

我正在使用 postgreSQL 9.1,我想使用以下提示从我的表中删除重复项: https://stackoverflow.com/a/3822833/2239537

所以,我的查询看起来像这样:

WITH cte
 AS (SELECT ROW_NUMBER() 
 OVER (PARTITION BY code, card_id, parent_id 
     ORDER BY id DESC) RN
     FROM card)
DELETE FROM cte
WHERE RN > 1

但它告诉我

ERROR: relation "cte" does not exist
SQL state: 42P01
Character: 157

但是这个语句可以正常工作:

WITH cte
 AS (SELECT ROW_NUMBER() 
 OVER (PARTITION BY code, card_id, parent_id 
     ORDER BY id DESC) RN
     FROM merchantcard)
SELECT * FROM cte
WHERE RN > 1

任何想法如何让它工作? 谢谢!

【问题讨论】:

    标签: sql postgresql postgresql-9.1


    【解决方案1】:

    这是因为 PostgreSQL 中的 CTE 与 SQL Server 中的 CTE 工作方式不同。在 SQL Server CTE 中就像一个可更新的视图,因此您可以从中删除或更新它们,而在 PostgreSQL 中则不能。

    你可以加入cte和delete,比如:

    with cte as (
        select
            id,
            row_number() over(partition by code, card_id, parent_id order by id desc) as rn
        from card
    )
    delete
    from card
    where id in (select id from cte where rn > 1)
    

    另一方面,您可以在 PostgreSQL 的 CTE 中编写 DDL 语句(请参阅documentation),这可能非常方便。例如,您可以删除 card 中的所有行,然后仅插入 row_number = 1 的行:

    with cte1 as (
        delete
        from card
        returning *
    ), cte2 as (
        select
            row_number() over(partition by code, card_id, parent_id order by id desc) as rn,
            *
        from cte1
    )
    insert into card
    select <columns here>
    from cte2
    where rn = 1
    

    【讨论】:

    • 哇,感谢您的快速回复和有用的答案!为我工作,只需要添加“从卡中删除”,但这只是错字,当然。
    • 第一个解决方案似乎为我删除了表中的所有行。我不明白 cte 的行为:如果我这样做 select count(1) from cte where rn &gt; 1 我得到正确的数字,但 select count(1) from card where id in (select id from cte where rn &gt; 1) 返回所有行
    • @ArkadiyKukarkin 难道id 不是唯一的吗?为了帮助您,最好了解更多关于您的结构和您想要获得的结果的信息
    • 点赞!这也适用于多列吗?
    • 这可用于对 Postgres 中的表进行重复数据删除。哇,我从试图在 Postgres 中删除完全重复的行并准备放弃,然后找到了这个黄金,它以一种有效的方式结合了我发现的其他东西。谢谢!
    【解决方案2】:

    我知道,您在问如何使用 WITH 语句解决问题,并且已经得到了很好的答案。但我建议在您链接的同一问题中查看替代方案。

    这个呢?

    DELETE FROM card
    WHERE id NOT IN (
      SELECT MIN(id) FROM card
      GROUP BY code, card_id, parent_id 
    );
    

    【讨论】:

    • 这是我见过的在 PostgreSQL 中检测和清除重复记录的最清晰的方法。谢谢。
    • 那么为什么我会得到这么多反对票?不告诉我是不公平的。
    • 可能是因为您的解决方案要求已经存在一个唯一键 (id) 可以在 where 中使用...原始问题没有其中之一
    【解决方案3】:

    对我来说,它在 Postgres/GreenPlum 中是这样工作的:

    delete
    from card where id in (
    with cte as (
        select
            id,
            row_number() over(partition by code, card_id, parent_id order by id desc) as rn
        from card
    )
    select id from cte where rn > 1);
    

    【讨论】:

      猜你喜欢
      • 2021-04-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2021-06-19
      • 1970-01-01
      相关资源
      最近更新 更多