使用CTE删除似乎不起作用

时间:2015-01-24 04:38:22

标签: sql postgresql greatest-n-per-group identifier sql-delete

我有以下使用多个CTE的查询:

;with Test as (select plan_id, max("id") maxid
from Scheme
group by plan_id),
Rec as (select rh.* from Scheme rh, Test
where rh.plan_id = Test.plan_id
and rh.id = Test.maxid
and rh.event_id = 20)
delete from Scheme rh USING Rec
where rh.id = "Rec".id;

我收到以下错误:

[Err] ERROR:  missing FROM-clause entry for table "Rec"
LINE 9: where rh.id = "Rec".id;

如果我只使用一个CTE重新编写查询,那么从"表"删除使用" CTE"语法有效。我在上述查询中遗漏了什么?

2 个答案:

答案 0 :(得分:4)

错误的实际原因是无偿的大写与错误的引用相结合:

...
delete from Scheme rh USING Rec
where rh.id = "Rec".id;

在Postgres中将不带引号的标识符强制转换为小写,并且实际上不区分大小写。如果你双引号,你需要匹配案例。 "Rec"Rec不同。详细说明:

您的声明已清理

WITH test AS (
   SELECT plan_id, max(id) AS id
   FROM   scheme
   GROUP  BY plan_id
   )
,  rec AS (
   SELECT s.*
   FROM   scheme s
   JOIN   test   t USING (plan_id, id)
   WHERE  s.event_id = 20
   )
DELETE FROM scheme s
USING  rec
WHERE  s.id = rec.id;

但这效率很低。有更好的方法可以识别idplan_id {。}}行最多的行。

使用DISTINCT ON和子查询而不是CTE

更短更快

DELETE FROM scheme s
USING (
   SELECT DISTINCT ON (plan_id)
          plan_id, id, event_id 
   FROM   scheme
   ORDER  BY plan_id, id DESC NULLS LAST
   ) r
WHERE  r.event_id = 20
AND    s.id = r.id;

DISTINCT ON的详细信息:

答案 1 :(得分:-3)

你可以这两种方式。

使用IN运算符删除记录。

WITH Test
     AS (SELECT plan_id,
                Max("id") maxid
         FROM   Scheme
         GROUP  BY plan_id),
     Rec
     AS (SELECT rh.*
         FROM   Scheme rh,
                Test
         WHERE  rh.plan_id = Test.plan_id
                AND rh.id = Test.maxid
                AND rh.event_id = 20)
DELETE FROM Scheme
WHERE  id IN(SELECT a.id
             FROM   rec a);

或者通过使用join也可以执行此操作,但Using构造将在两个表之间具有公共列而不是表名。

WITH Test
     AS (SELECT plan_id,
                Max("id") maxid
         FROM   Scheme
         GROUP  BY plan_id),
     Rec
     AS (SELECT rh.*
         FROM   Scheme rh,
                Test
         WHERE  rh.plan_id = Test.plan_id
                AND rh.id = Test.maxid
                AND rh.event_id = 20)
DELETE FROM Scheme join rec using(id);