将两列和两行聚合成一行。

4
我有以下表格结构。
start|end
09:00|11:00
13:00|14:00

我知道

SELECT ARRAY_AGG(start), ARRAY_AGG(end)

将会导致
start|end
[09:00,13:00]|[11:00,14:00]

但是我怎么能得到以下结果?结果。
[09:00,11:00,13:00,14:00]

顺便提一下,我正在使用Postgres


startend的数据类型是什么? - Vivek S.
没有时区的时间戳 - Guilherme Miranda
3个回答

5

如果顺序不重要,您可以进行数组连接:

SELECT ARRAY_AGG(start) || ARRAY_AGG(end) FROM TABLE1

如果顺序很重要,您可以使用戈登(Gordon)的方法,但是:
  • add aggregate order array_agg(d order by d ASC)
  • use unnest instead of union all, because Gordon's solution (union all) performs two sequence scan. If table is big it could be better for performance to use:

    SELECT array_agg(d ORDER BY d ASC) FROM(
        SELECT unnest(ARRAY[start] || ARRAY[end]) as d from table1
    ) sub
    

仅对表进行一次序列扫描(速度更快)。


谢谢Gabriel,但是订单很重要。 - Guilherme Miranda
@GuilhermeMiranda 我已经编辑了我的答案,加入了考虑顺序。 - Gabriel's Messanger

1
一种方法是将它们转换为长格式,然后聚合:
select array_agg(d)
from (select start as d from t
      union all
      select end as d from t
     ) t;

一种类似的方法使用 cross join
select array_agg(case when n.n = 1 then t.start else t.end end)
from t cross join
     (select 1 as n union all select 2) n;

根据 OP 的数据,这样做会得到 [09:00,13:00,11:00,14:00],但我不确定 OP 是否关心顺序。如果顺序很重要,你的答案好像缺少了一部分。 - Mureinik
@GordonLinoff 可能需要添加聚合排序 array_agg(d order by d) 以获得问题中发布的确切结果。 - Gabriel's Messanger
@GordonLinoff 此外,如果他需要在整个表上执行此操作,则在大表上使用 union all 可能比我在 我的答案 中解释的 unnest 更慢。 - Gabriel's Messanger
@Gabriel的信使……cross join不应该进行两次连续扫描。 - Gordon Linoff
@GordonLinoff 是的,那是真的。但你展示了两种方法。我在谈论第一种方法。 - Gabriel's Messanger

0

我假设startend字符类型

select ARRAY_AGG(col) 
from(select string_agg(strt::text||','||en::text,',') col 
     from b
)t

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接