使用 CTE 删除似乎不起作用
DELETE using CTEs does not seem to work
我有以下使用多个 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 重写查询,则 delete from "table" USING "CTE" 语法有效。我在上述查询中遗漏了什么?
您可以通过两种方式执行此操作。
使用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
构造将具有两个 table 之间的公共列,而不是 table 名称。
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);
错误的实际原因是无端大写加上不正确的引用:
...
delete from Scheme rh USING <b>Rec</b>
where rh.id = <b>"Rec"</b>.id;
未加引号的标识符在 Postgres 中被强制转换为小写并且有效地不区分大小写。如果双引号,则需要匹配大小写。 "Rec"
与 Rec
不同。详情:
- Are PostgreSQL column names case-sensitive?
你的声明已清理:
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;
但这相当低效。有更好的方法来识别每个 plan_id
.
具有最大 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
的详细信息:
- Select first row in each GROUP BY group?
我有以下使用多个 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 重写查询,则 delete from "table" USING "CTE" 语法有效。我在上述查询中遗漏了什么?
您可以通过两种方式执行此操作。
使用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
构造将具有两个 table 之间的公共列,而不是 table 名称。
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);
错误的实际原因是无端大写加上不正确的引用:
...
delete from Scheme rh USING <b>Rec</b>
where rh.id = <b>"Rec"</b>.id;
未加引号的标识符在 Postgres 中被强制转换为小写并且有效地不区分大小写。如果双引号,则需要匹配大小写。 "Rec"
与 Rec
不同。详情:
- Are PostgreSQL column names case-sensitive?
你的声明已清理:
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;
但这相当低效。有更好的方法来识别每个 plan_id
.
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
的详细信息:
- Select first row in each GROUP BY group?