2013-08-26 7 views
5

を「関係が存在しません」私は、PostgreSQL 9.1を使用していますが、私はこのヒントを使用して、私のテーブルから重複を削除する: https://stackoverflow.com/a/3822833/2239537のPostgreSQLで、削除

だから、私のクエリは以下のようになります。

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 

どのようにすればよいですか? ありがとう!

答えて

14

これは、PostgreSQLのCTEがSQL ServerのCTEとは異なる動作をするためです。 SQL ServerのCTEでは、更新可能なビューのようなものなので、PostgreSQLでは削除できません。あなたのような、CTEに参加し、削除することができ

:一方

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 
+0

うわー、おかげで迅速な回答、有用な答えを!私のために働いた、 "削除FROMカード"を追加するだけでしたが、これはもちろん、タイプミスです。 –

+0

@AlexKartishevはい、ありがとう、更新済み –

+0

最初の解決策は、私のためにテーブルのすべての行を削除するようです。私はcteの動作を理解していません: 'select count(1)from cn where rn> 'を実行すると正しい番号が得られますが、' select count(1) 1) 'はすべての行を返します –

5

を私は知っているが、あなたはWITHステートメントを使用して、あなたの問題を解決する方法を尋ねると、すでに良い答えを持っています。しかし、あなたがリンクしたのと同じ質問で代替案を検討することをお勧めします。

この場合はどうなりますか?

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

これは、私がPostgreSQLで重複したレコードを検出してクリーンアップするのに見ている最も分かりやすい方法です。これは、あなたの構造と結果についてより多くの情報を得ることをお手伝いします。ありがとうございました。 –

+0

なぜ私は非常に多くのdownvotesを得るのですか?私に言わないと公平ではありません。 –

+0

おそらく、あなたのソリューションでは、どこで使用できる一意のキー(ID)が既に存在する必要があるからです。元の質問にはそれらのキー –

0

は、私にとっては、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); 
関連する問題