我有一个目标表(已填充数据)和另一个(源表),我需要将数据检索到第一个。
target_table
postgres=# select id,id_user from ttasks; id | id_user ----+--------- 1 | 2 | 3 | 4 | 5 | (5 rows)
source_table
postgres=# select id from tusers where active; id ------ 1011 1012 1013 1014 (4 rows)
我需要使用来自tusers表的id来更新ttasks表的id_user列,因此ttasks上的最终结果应为:
# expected result after update [select id, id_user from ttasks;] id | id_user ----+--------- 1 | 1011 2 | 1012 3 | 1013 4 | 1014 5 | 1011 (5 rows)
我尝试过(类似于INSERT ... FROM ...语句):
postgres=# update ttasks t1 set id_user = q1.id from (select id from tusers where active) q1 returning t1.id,t1.id_user; id | id_user ----+--------- 1 | 1011 2 | 1011 3 | 1011 4 | 1011 5 | 1011 (5 rows)
但是这个查询总是使用q1子查询中的第一个id。
有关如何完成此任务的任何想法,帮助甚至解决方案? 非常感谢你!
P.S。这是我在这个社区的第一篇文章,所以如果我的问题中的某些内容不符合你的规则,请对我保持温和。
答案 0 :(得分:0)
最后,在我的一个朋友告诉我并非一切都可以用“保持愚蠢的简单”方式编码之后,我编写了一个plpqsql(PL / PGSQL)函数来完成这项工作,并且允许在里面使用一些高级过滤器。
CREATE OR REPLACE FUNCTION assign_workers_to_tasks(i_workers_table regclass, i_workers_table_tc text, i_tasks_table regclass, i_tasks_table_tc text, i_workers_filter text DEFAULT ''::text, i_tasks_filter text DEFAULT ''::text) RETURNS void AS $BODY$ DECLARE workers int[]; i integer; total_workers integer; r record; get_tasks text; begin i_workers_filter := 'where '||nullif(i_workers_filter,''); i_tasks_filter := 'where '||nullif(i_tasks_filter,''); EXECUTE format('select array_agg(%s) from (select %s from %s %s order by %s) q', i_workers_table_tc, i_workers_table_tc,i_workers_table, i_workers_filter,i_workers_table_tc) INTO workers; --available [filtered] workers total_workers := coalesce(array_length(workers,1),0); --total of available [filtered] workers IF total_workers = 0 THEN EXECUTE format('update %s set %s=null %s', i_tasks_table, i_tasks_table_tc, i_tasks_filter); RETURN; END IF; i :=1; get_tasks := format('select * from %s %s',i_tasks_table,i_tasks_filter); --[filtered] tasks FOR r IN EXECUTE (get_tasks) LOOP EXECUTE format('update %s set %s=%s where id = %s', i_tasks_table, i_tasks_table_tc, workers[i],r.id); i := i+1; IF i>total_workers THEN i := 1; END IF; END LOOP; RETURN; end; $BODY$ LANGUAGE plpgsql VOLATILE COST 100; ALTER FUNCTION assign_workers_to_tasks(regclass, text, regclass, text, text, text) OWNER TO postgres;
并完成我自己的问题:
select assign_workers_to_tasks('tusers','id','ttasks','id_user','active');