postgresql 如何在Postgres中删除CTE(公共表表达式)中的记录

xwbd5t1u  于 2023-08-04  发布在  PostgreSQL
关注(0)|答案(5)|浏览(126)

我在Postgres中使用CTE编写了以下查询。现在我无法从中删除记录。

WITH cte AS (
    SELECT 
   
        firstname, 
        lastname, 
        country, 
        ROW_NUMBER() OVER (
            PARTITION BY 
                firstname, 
                lastname, 
                country
        ) row_num
     FROM 
        employee
) 
delete  from cte
where row_num >1

字符串
当我运行这个查询时,它显示错误:
关系“cte”不存在
这里是我的表'雇员'的样本

id  firstname  lastname  country
1   "Raj"      "Gupta"   "India"
2   "Raj"      "Gupta"   "India"
3   "Mohan"    "Kumar"   "USA"
4   "James"    "Barry"   "UK"
5   "James"    "Barry"   "UK"
6   "James"    "Barry"   "UK"

jw5wzhpr

jw5wzhpr1#

无法从CTE中删除。
你可以这样做:
demo:db<>fiddle

DELETE FROM employee
WHERE id IN (
    SELECT
        id
    FROM (
        SELECT
            id,
            ROW_NUMBER() OVER (PARTITION BY firstname, lastname, country) row_num
        FROM 
            employee
    ) s
    WHERE row_num > 1
)

字符串
如果你想使用CTE,你可以将子查询移动到一个:
demo:db<>fiddle

WITH cte AS (
    SELECT
        id
    FROM (
        SELECT
            id,
            ROW_NUMBER() OVER (PARTITION BY firstname, lastname, country) row_num
        FROM 
            employee
    ) s
    WHERE row_num > 1
)
DELETE FROM employee
WHERE id IN (SELECT * FROM cte)

bvn4nwqk

bvn4nwqk2#

你不能在postgresql中删除CTE表中的记录。尽管在其他数据库服务器(如SQLSERVER)中也可以。你可以看到CTE的postgresql文档。

fkvaft9z

fkvaft9z3#

我建议使用:

delete from employee e
    where e.id > (select min(e2.id)
                  from employee e2
                  where e2.firstname = e.firstname and
                        e2.lastname = e.lastname and 
                        e2.country = e.country
                 );

字符串
这是标准的SQL,可以在SQL Server和Postgres中工作。
与SQL Server版本的唯一区别是如何处理NULL值。这将它们视为“不同”,因此匹配的NULL值不会被视为匹配。这在您的数据中可能不是问题,但您可以用途:

where e2.firstname is not distinct from e.firstname and
                        e2.lastname is not distinct from e.lastname and 
                        e2.country is not distinct from e.country


如果您希望NULL值匹配。
请注意,原始版本应该能够使用(lastname, firstname, country, id)上的索引(在任一数据库中)。

7nbnzgx9

7nbnzgx94#

这对我很有效,因为你不能在postgres上删除cte:

CREATE TEMPORARY TABLE temp_table AS 
SELECT DISTINCT ON (id) * FROM your_table;
DELETE FROM your_table;
INSERT INTO your_table SELECT * FROM temp_table;

字符串

ev7lccsx

ev7lccsx5#

我认为更好的情况将只是过滤不需要的行的步骤创建CTE(没有任何删除)

WITH cte AS (
    SELECT 
        firstname, 
        lastname, 
        country, 
        ROW_NUMBER() OVER (
            PARTITION BY 
                firstname, 
                lastname, 
                country
        ) row_num
     FROM employee
     WHERE row_num >1
)

字符串

相关问题