PostgreSQL CTE UPDATE-FROM 查询跳过行
PostgreSQL CTE UPDATE-FROM query skips rows
2 桌
table_1 行:注意:id 2 有两行
-----------------------
| id | counts | track |
-----------------------
| 1 | 10 | 1 |
| 2 | 10 | 2 |
| 2 | 10 | 3 |
-----------------------
table_2 行
---------------
| id | counts |
---------------
| 1 | 0 |
| 2 | 0 |
---------------
查询:
with t1_rows as (
select id, sum(counts) as counts, track
from table_1
group by id, track
)
update table_2 set counts = (coalesce(table_2.counts, 0) + t1.counts)::float
from t1_rows t1
where table_2.id = t1.id;
select * from table_2;
当我 运行 以上查询时,我得到 table_2 输出为
---------------
| id | counts |
---------------
| 1 | 10 |
| 2 | 10 | (expected counts as 20 but got 10)
---------------
我注意到上面的更新查询只考虑了第一个匹配项并跳过了其余部分。
我可以通过如下更改查询来使其工作。现在 table_2 按预期更新,因为 table_1.
中没有重复的行
但我想知道为什么我之前的查询不起作用。有什么问题吗?
with t1_rows as (
select id, sum(counts) as counts, array_agg(track) as track
from table_1
group by id
)
update table_2 set counts = (coalesce(table_2.counts, 0) + t1.counts)::float
from t1_rows t1
where table_2.id = t1.id;
架构
CREATE TABLE IF NOT EXISTS table_1(
id varchar not null,
counts integer not null,
track integer not null
);
CREATE TABLE IF NOT EXISTS table_2(
id varchar not null,
counts integer not null
);
insert into table_1(id, counts, track) values(1, 10, 1), (2, 10, 2), (2, 10, 3);
insert into table_2(id, counts) values(1, 0), (2, 0);
所以如果我没看错你的问题,你希望 table_1 的第 2 行和第 3 行加在一起?如果是这样,您的第一种方法不起作用的原因是因为它 grouped by id, track.
由于第 2 行和第 3 行在轨道列中的编号不同,因此 group by 子句不会将它们加在一起。
你的第二种方法奏效了,因为它只按 id 分组
问题是 PostgreSQL 中的 UPDATE
创建行的新版本而不是就地更改行,但新行版本在当前查询的快照中不可见。所以从查询的角度来看,该行在第一次更新时“消失”了。
When a FROM
clause is present, what essentially happens is that the target table is joined to the tables mentioned in the <strong><em>from_list</em></strong>
, and each output row of the join represents an update operation for the target table. When using FROM
you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn't join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.
2 桌
table_1 行:注意:id 2 有两行
-----------------------
| id | counts | track |
-----------------------
| 1 | 10 | 1 |
| 2 | 10 | 2 |
| 2 | 10 | 3 |
-----------------------
table_2 行
---------------
| id | counts |
---------------
| 1 | 0 |
| 2 | 0 |
---------------
查询:
with t1_rows as (
select id, sum(counts) as counts, track
from table_1
group by id, track
)
update table_2 set counts = (coalesce(table_2.counts, 0) + t1.counts)::float
from t1_rows t1
where table_2.id = t1.id;
select * from table_2;
当我 运行 以上查询时,我得到 table_2 输出为
---------------
| id | counts |
---------------
| 1 | 10 |
| 2 | 10 | (expected counts as 20 but got 10)
---------------
我注意到上面的更新查询只考虑了第一个匹配项并跳过了其余部分。
我可以通过如下更改查询来使其工作。现在 table_2 按预期更新,因为 table_1.
中没有重复的行但我想知道为什么我之前的查询不起作用。有什么问题吗?
with t1_rows as (
select id, sum(counts) as counts, array_agg(track) as track
from table_1
group by id
)
update table_2 set counts = (coalesce(table_2.counts, 0) + t1.counts)::float
from t1_rows t1
where table_2.id = t1.id;
架构
CREATE TABLE IF NOT EXISTS table_1(
id varchar not null,
counts integer not null,
track integer not null
);
CREATE TABLE IF NOT EXISTS table_2(
id varchar not null,
counts integer not null
);
insert into table_1(id, counts, track) values(1, 10, 1), (2, 10, 2), (2, 10, 3);
insert into table_2(id, counts) values(1, 0), (2, 0);
所以如果我没看错你的问题,你希望 table_1 的第 2 行和第 3 行加在一起?如果是这样,您的第一种方法不起作用的原因是因为它 grouped by id, track.
由于第 2 行和第 3 行在轨道列中的编号不同,因此 group by 子句不会将它们加在一起。
你的第二种方法奏效了,因为它只按 id 分组
问题是 PostgreSQL 中的 UPDATE
创建行的新版本而不是就地更改行,但新行版本在当前查询的快照中不可见。所以从查询的角度来看,该行在第一次更新时“消失”了。
When a
FROM
clause is present, what essentially happens is that the target table is joined to the tables mentioned in the<strong><em>from_list</em></strong>
, and each output row of the join represents an update operation for the target table. When usingFROM
you should ensure that the join produces at most one output row for each row to be modified. In other words, a target row shouldn't join to more than one row from the other table(s). If it does, then only one of the join rows will be used to update the target row, but which one will be used is not readily predictable.