如何根据 PostgreSQL 中同一行的两个不同列更新具有唯一序列号的列?
How to update a column with unique serial number depending on two different columns of the same rows in PostgreSQL?
我有一个以下格式(示例)的记录列表,由连接数据库中的多个表和条件:
生成
Col1
Col2
Col3
100
200
1
100
201
1
100
202
1
100
203
1
101
204
1
101
205
1
102
206
1
102
207
1
我想要的是根据 Col1 和 Col2 中的值更新上例中 Col3 中的值。
想法是先循环 Col1,然后循环 Col2 中的另一个循环,并从 1 开始更新 Col3 中的值,每次迭代 Col2 记录时递增 1。这应该在 Col1 的下一次迭代中再次重复。
上述方法的预期输出示例是:
Col1
Col2
Col3
100
200
1
100
201
2
100
202
3
100
203
4
101
204
1
101
205
2
102
206
1
102
207
2
使用的数据库是postgres,我对postgres中的cursor等功能还比较陌生。
如果有人对此有任何见解并有一种有效的方法来解决这个问题,那就太好了。
感谢您的帮助。
谢谢
您可以借助相关计数子查询来表达更新:
UPDATE yourTable t1
SET Col3 = (SELECT COUNT(*) FROM yourTable t2
WHERE t2.Col1 = t1.Col1 AND t2.Col2 <= t1.Col2);
假设您向我们展示的输出是由联接产生的,您使用的实际查询可能比上面的查询稍微复杂一些。但是,您应该能够遵循相同的模式。请注意,我的回答还假设与每个 Col1
值关联的 Col2
值始终是唯一的。
您可以使用 row_number()over()
排名 window 函数轻松实现:
架构和插入语句:
create table table1(Col1 int, Col2 int,Col3 int);
insert into table1 values(100 ,200 ,1);
insert into table1 values(100 ,201 ,1);
insert into table1 values(100 ,202 ,1);
insert into table1 values(100 ,203 ,1);
insert into table1 values(101 ,204 ,1);
insert into table1 values(101 ,205 ,1);
insert into table1 values(102 ,206 ,1);
更新查询:
with cte as(
select col1,col2,col3, row_number()over (partition by col1 order by col2) rn from table1
)
update table1 set col3=cte.rn
from cte
where table1.col1=cte.col1 and table1.col2=cte.col2;
在上面的查询中,row_number()over (partition by col1 order by col2)
将为 col1 中的每个不同值生成一个唯一序列,从 1 开始并按 col2 排序。
Select查询:
select * from table1;
输出:
col1
col2
col3
100
200
1
100
201
2
100
202
3
100
203
4
101
204
1
101
205
2
102
206
1
db<>fiddle here
我有一个以下格式(示例)的记录列表,由连接数据库中的多个表和条件:
生成Col1 | Col2 | Col3 |
---|---|---|
100 | 200 | 1 |
100 | 201 | 1 |
100 | 202 | 1 |
100 | 203 | 1 |
101 | 204 | 1 |
101 | 205 | 1 |
102 | 206 | 1 |
102 | 207 | 1 |
我想要的是根据 Col1 和 Col2 中的值更新上例中 Col3 中的值。
想法是先循环 Col1,然后循环 Col2 中的另一个循环,并从 1 开始更新 Col3 中的值,每次迭代 Col2 记录时递增 1。这应该在 Col1 的下一次迭代中再次重复。
上述方法的预期输出示例是:
Col1 | Col2 | Col3 |
---|---|---|
100 | 200 | 1 |
100 | 201 | 2 |
100 | 202 | 3 |
100 | 203 | 4 |
101 | 204 | 1 |
101 | 205 | 2 |
102 | 206 | 1 |
102 | 207 | 2 |
使用的数据库是postgres,我对postgres中的cursor等功能还比较陌生。 如果有人对此有任何见解并有一种有效的方法来解决这个问题,那就太好了。
感谢您的帮助。
谢谢
您可以借助相关计数子查询来表达更新:
UPDATE yourTable t1
SET Col3 = (SELECT COUNT(*) FROM yourTable t2
WHERE t2.Col1 = t1.Col1 AND t2.Col2 <= t1.Col2);
假设您向我们展示的输出是由联接产生的,您使用的实际查询可能比上面的查询稍微复杂一些。但是,您应该能够遵循相同的模式。请注意,我的回答还假设与每个 Col1
值关联的 Col2
值始终是唯一的。
您可以使用 row_number()over()
排名 window 函数轻松实现:
架构和插入语句:
create table table1(Col1 int, Col2 int,Col3 int);
insert into table1 values(100 ,200 ,1);
insert into table1 values(100 ,201 ,1);
insert into table1 values(100 ,202 ,1);
insert into table1 values(100 ,203 ,1);
insert into table1 values(101 ,204 ,1);
insert into table1 values(101 ,205 ,1);
insert into table1 values(102 ,206 ,1);
更新查询:
with cte as(
select col1,col2,col3, row_number()over (partition by col1 order by col2) rn from table1
)
update table1 set col3=cte.rn
from cte
where table1.col1=cte.col1 and table1.col2=cte.col2;
在上面的查询中,row_number()over (partition by col1 order by col2)
将为 col1 中的每个不同值生成一个唯一序列,从 1 开始并按 col2 排序。
Select查询:
select * from table1;
输出:
col1 | col2 | col3 |
---|---|---|
100 | 200 | 1 |
100 | 201 | 2 |
100 | 202 | 3 |
100 | 203 | 4 |
101 | 204 | 1 |
101 | 205 | 2 |
102 | 206 | 1 |
db<>fiddle here