请考虑以下事项:
create table tmp.x (i integer, t text);
create table tmp.y (i integer, t text);
delete from tmp.x;
delete from tmp.y;
insert into tmp.x values (1, 'hi');
insert into tmp.y values(1, 'there');
insert into tmp.y values(1, 'wow');
在上面,表x
中有一行,我想要更新。在表格y
中,有两行,我想要将这两行输入"将数据输入"更新。
以下是我的尝试:
update tmp.x
set t = x.t || y.t
from ( select * from tmp.y order by t desc ) y
where y.i = x.i;
select * from tmp.x;
我希望x.t
的值为'hiwowthere'
,但该值最终为'hiwow'
。我相信原因是update语句中的子查询返回两行(y.t
值'wow'
首先返回),而where
子句y.i = x.i
只返回匹配第一行。
我可以使用单个update
语句获得所需的结果吗?如果是,那该怎么做?
更新:上述text
类型的使用仅用于说明目的。我实际上并不想使用我在这里发布的json_set
函数(How do I modify fields inside the new PostgreSQL JSON datatype?)来修改文本内容,而是修改JSON内容,尽管我希望这个原则可以应用于任何函数,比如虚构的concat_string(column_name, 'string-to-append')
。
更新2:我实际上写了一个小函数来完成它,而不是在这个问题上浪费时间。但是,知道这是否可行仍然很好,如果可行,如何。
答案 0 :(得分:3)
您可以使用string_agg建立一个连接字符串,按integer i
分组,然后您可以在更新期间加入该字符串:
update tmp.x
set t = x.t || y.txt
from (select i, string_agg(t, '') as txt
from(
select tmp.y.i,tmp.y.t
from tmp.y
order by t desc
) z
group by z.i) y
where y.i = x.i ;
为了保留订单,您可能需要一个额外的包装派生表。 SqlFiddle here
答案 1 :(得分:1)
使用string_agg
,如下所示:
update tmp.x x
set t = x.t || (
select string_agg(t,'' order by t desc)
from tmp.y where i = x.i
group by i
)
答案 2 :(得分:0)
with cte as (
select y.i, string_agg(t, '' order by t desc) as txt
from y
group by y.i
)
update x set t= x.t||cte.txt
from cte where cte.i=x.i