Postgresql使用CTE删除行删除所有行
Postgresql Using CTE to delete rows removes all rows
我有以下 table:
DROP TABLE IF EXISTS test;
CREATE TABLE test (
id SERIAL,
username varchar(32)
);
INSERT INTO test (username)
VALUES ('Jesse'), ('Jesse'), ('Scott'), ('Scott'), ('John');
我想在有重复行时删除最低的ID。我进行了以下查询以查找目标行:
SELECT MIN(id), username
FROM test
GROUP BY username
HAVING count(*) > 1;
当我尝试在 CTE 中使用它时,它最终删除了每一行:
WITH to_delete AS (
SELECT MIN(id), username
FROM test
GROUP BY username
HAVING count(*) > 1
)
DELETE FROM test
WHERE id IN (
SELECT id
FROM to_delete
);
但是,当我 运行 相同的查询并将 CTE 作为子查询时,它按预期工作:
DELETE FROM test
WHERE id IN (
SELECT MIN(id)
FROM test
GROUP BY username
HAVING count(*) > 1
);
我确信这背后有一定的逻辑,但我在搜索中没有找到来源。为什么 CTE 删除了每一行,但子查询按预期工作?
向 CTE 添加列别名可使 DELETE 按预期工作。
with
to_delete as (
select
min(id) as id,
username
from
test
group by
username
having
count(*) > 1
)
delete from
test
where
id in (
select
id
from
to_delete
)
;
table test;
id │ username
════╪══════════
7 │ Jesse
9 │ Scott
10 │ John
(3 rows)
IN 运算符需要具有单列的 table。您的子查询仅包含一列,因此名称无关紧要(postgres 会将函数的名称分配给该列,因此 min
而不是 id
)。您的 CTE 包含两列,因此您编写了一个子查询来选择其中一列,但它没有正确地别名为 id
.
with
to_delete as (
select
min(id) as id,
username
from
test
group by
username
having
count(*) > 1
)
select id from to_delete;
结果出错
ERROR: 42703: column "id" does not exist
LINE 15: select id from to_delete;
有趣的是,DELETE 语句没有出错,而是将 WHERE 子句视为不存在并继续删除所有内容,这是我没有预料到的行为。
我有以下 table:
DROP TABLE IF EXISTS test;
CREATE TABLE test (
id SERIAL,
username varchar(32)
);
INSERT INTO test (username)
VALUES ('Jesse'), ('Jesse'), ('Scott'), ('Scott'), ('John');
我想在有重复行时删除最低的ID。我进行了以下查询以查找目标行:
SELECT MIN(id), username
FROM test
GROUP BY username
HAVING count(*) > 1;
当我尝试在 CTE 中使用它时,它最终删除了每一行:
WITH to_delete AS (
SELECT MIN(id), username
FROM test
GROUP BY username
HAVING count(*) > 1
)
DELETE FROM test
WHERE id IN (
SELECT id
FROM to_delete
);
但是,当我 运行 相同的查询并将 CTE 作为子查询时,它按预期工作:
DELETE FROM test
WHERE id IN (
SELECT MIN(id)
FROM test
GROUP BY username
HAVING count(*) > 1
);
我确信这背后有一定的逻辑,但我在搜索中没有找到来源。为什么 CTE 删除了每一行,但子查询按预期工作?
向 CTE 添加列别名可使 DELETE 按预期工作。
with
to_delete as (
select
min(id) as id,
username
from
test
group by
username
having
count(*) > 1
)
delete from
test
where
id in (
select
id
from
to_delete
)
;
table test;
id │ username
════╪══════════
7 │ Jesse
9 │ Scott
10 │ John
(3 rows)
IN 运算符需要具有单列的 table。您的子查询仅包含一列,因此名称无关紧要(postgres 会将函数的名称分配给该列,因此 min
而不是 id
)。您的 CTE 包含两列,因此您编写了一个子查询来选择其中一列,但它没有正确地别名为 id
.
with
to_delete as (
select
min(id) as id,
username
from
test
group by
username
having
count(*) > 1
)
select id from to_delete;
结果出错
ERROR: 42703: column "id" does not exist
LINE 15: select id from to_delete;
有趣的是,DELETE 语句没有出错,而是将 WHERE 子句视为不存在并继续删除所有内容,这是我没有预料到的行为。