that's because CTE in PostgreSQL works differently than CTE in SQL Server. In SQL Server CTE are like an updatable views, so you can delete from them or update them, in PostgreSQL you cannot.
you can join cte and delete, like:
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)
On the other hand, you can write DDL statements inside CTE in PostgreSQL (see documentation) and this could be very handy. For example, you can delete all rows from card
and then insert only those having 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
与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…