PostgreSQL:选择字段值并使用第二个表中的下一个值进行更新
使用上述表格,我想PostgreSQL:选择字段值并使用第二个表中的下一个值进行更新,sql,postgresql,Sql,Postgresql,使用上述表格,我想从t_b中选择a_id_fk,其中b_id=1,然后用序列中的下一个a_id更新a_id_fk,但如果我在可用的a_id的末尾,我会循环回到第一个。所有这些都需要多人从t\u b查询/更新特定行 如果有帮助的话,我正在研究的场景是,多个站点共享一个共同的单词列表,但是当每个站点的每个用户抓取一个单词时,单词列表中的站点索引将移动到下一个单词,直到它到达末尾,然后循环回到开头 有没有一种方法可以在单个查询中实现这一点?如果没有,处理这个问题的最佳方法是什么?我可以处理大部分逻辑,
从t_b中选择a_id_fk,其中b_id=1
,然后用序列中的下一个a_id
更新a_id_fk,但如果我在可用的a_id
的末尾,我会循环回到第一个。所有这些都需要多人从t\u b
查询/更新特定行
如果有帮助的话,我正在研究的场景是,多个站点共享一个共同的单词列表,但是当每个站点的每个用户抓取一个单词时,单词列表中的站点索引将移动到下一个单词,直到它到达末尾,然后循环回到开头
有没有一种方法可以在单个查询中实现这一点?如果没有,处理这个问题的最佳方法是什么?我可以处理大部分逻辑,当我用完ID时,它会循环返回,这让我感到困惑。你可以使用一些复杂的东西,比如
CREATE TABLE t_a
(
a_id SERIAL PRIMARY KEY,
str VARCHAR(50)
)
CREATE TABLE t_b
(
b_id SERIAL PRIMARY KEY,
a_id_fk INTEGER REFERENCES (t_a(a_id),
)
但是如果给我一个这样的要求,我可能会维护一个辅助表,将一个a_id映射到循环中的下一个a_id…这个比@pdw的解决方案更优雅(IMHO):
UPDATE t_b
SET a_id_fk = COALESCE(
(SELECT MIN(a_id) FROM t_a WHERE a_id > t_b.a_id_fk),
(SELECT MIN(a_id) FROM t_a))
WHERE b_id = :b_id
结果:
DROP SCHEMA tmp CASCADE;
CREATE SCHEMA tmp ;
SET search_path=tmp;
CREATE TABLE t_a
( a_id SERIAL PRIMARY KEY
, str VARCHAR(50)
);
CREATE TABLE t_b
( b_id SERIAL PRIMARY KEY
, a_id_fk INTEGER REFERENCES t_a(a_id)
);
INSERT INTO t_a(str)
SELECT 'Str_' || gs::text
FROM generate_series(1,10) gs
;
INSERT into t_b(a_id_fk)
SELECT a_id FROM t_a
ORDER BY a_id
;
-- EXPLAIN ANALYZE
WITH src AS (
SELECT a_id AS a_id
, min(a_id) OVER (order BY a_id) AS frst
, lead(a_id) OVER (order BY a_id) AS nxt
FROM t_a
)
UPDATE t_b dst
SET a_id_fk = COALESCE(src.nxt, src.frst)
FROM src
WHERE dst.a_id_fk = src.a_id
AND dst.b_id IN ( 3, 10)
;
SELECT * FROM t_b
ORDER BY b_id
;
那很好。祝你好运。你有问题吗?你想更新t_b.a_id_fk吗?新值应该是什么?新值将是下一个t_a.a_id,当按a_id排序时,除非没有,否则它将从开头开始。从头开始并不容易。我从未想过在联合中使用查询,但我想这会奏效。我如何构造一个辅助表来处理这个问题,它是否能够为
tub
中的每个条目维护一个单独的索引?
DROP SCHEMA
CREATE SCHEMA
SET
CREATE TABLE
CREATE TABLE
INSERT 0 10
INSERT 0 10
UPDATE 2
b_id | a_id_fk
------+---------
1 | 1
2 | 2
3 | 4
4 | 4
5 | 5
6 | 6
7 | 7
8 | 8
9 | 9
10 | 1
(10 rows)