【问题标题】:Concatenate array elements on a joined table PostgreSQL在连接表 PostgreSQL 上连接数组元素
【发布时间】:2016-07-13 19:37:58
【问题描述】:

如果我有这样的查询,是否可以进行 1 对 1 元素数组连接:

编辑: 数组并不总是具有相同数量的元素。 可能是 array1 有时有 4 个元素,而 array2 有 8 个元素。

drop table if exists a;
drop table if exists b;
create temporary table a as (select 1 as id,array['a','b','c'] as array1);
create temporary table b as (select 1 as id,array['x','y','z'] as array2);

select
a.id,
a.array1,
b.array2,
array_concat--This has to be a 1 to 1 ordered concatenation (see                   
            --example below)
from a
left join b on b.id=a.id

我想在这里获得的是数组 1 和 2 的配对串联,如下所示:

id       array11          array2         array_concat
 1    ['a','b','c']   ['d','e','f']   ['a-d','b-e','c-f']
 2    ['x','y','z']   ['i','j','k']   ['x-i','y-j','z-k']
 3    ...

我尝试使用 unnest,但无法正常工作:

    select
    a.id,
    a.array1,
    b.array2,
    array_concat
    from table a
    left join b on b.id=a.id
    left join (select a.array1,b.array2, array_agg(a1||b2)
                      FROM unnest(a.array1, b.array2) 
                           ab (a1, b2)
              ) ag on ag.array1=a.array1 and  ag.array2=b.array2
;

编辑:

这只适用于一张桌子:

SELECT array_agg(el1||el2)
FROM unnest(ARRAY['a','b','c'], ARRAY['d','e','f']) el (el1, el2);

++感谢https://stackoverflow.com/users/1463595/%D0%9D%D0%9B%D0%9E

编辑:

我得出了一个非常接近的解决方案,但是一旦数组之间的连接完成,它就会混淆一些中间值,但我仍然需要一个完美的解决方案......

我现在使用的方法是:

1) 基于 2 个单独的表创建一个表 2) 使用横向聚合:

create temporary table new_table as
SELECT
    id,
    a.a,
    b.b
    FROM a a
    LEFT JOIN b b on a.id=b.id;

SELECT id,
       ab_unified
       FROM pair_sources_mediums_campaigns,
       LATERAL (SELECT ARRAY_AGG(a||'[-]'||b order by grp1) as ab_unified
               FROM (SELECT DISTINCT case when a null
                                   then 'not tracked'
                                   else a
                                   end as a
                         ,case when b is null
                                   then 'none'
                                   else b
                                   end as b
                            ,rn - ROW_NUMBER() OVER(PARTITION BY a,b ORDER BY rn) AS grp1

                    FROM unnest(a,b) with ordinality as el (a,b,rn)
                ) AS sub
           ) AS lat1
           order by 1;

【问题讨论】:

  • 旁注:正确的 JSON 是 " 而不是 '
  • 在PostgreSQL中你也可以定义包含数组的字符串为:select array['a','b','c'] as array1;

标签: arrays postgresql concatenation unnest


【解决方案1】:

类似的东西。

with a_elements (id, element, idx) as (
  select a.id,
         u.element, 
         u.idx
  from a 
    cross join lateral unnest(a.array1) with ordinality as u(element, idx)
), b_elements (id, element, idx) as (
  select b.id,
         u.element, 
         u.idx
  from b
    cross join lateral unnest(b.array2) with ordinality as u(element, idx)
)
select id,
       array_agg(concat_ws('-', a.element, b.element) order by idx) as elements
from a_elements a
  full outer join b_elements b using (id, idx)
group by coalesce(a.id, b.id);

连接运算符using (..) 将自动从连接表中获取非空值。这消除了使用例如coalesce(a.id, b.id).n

对于大桌子来说,它并不漂亮,而且绝对没有效率,但似乎可以满足您的所有需求。

对于元素数量不同的数组,结果将仅包含其中一个数组中的元素。

对于这个数据集:

insert into a 
  (id, array1)
values
  (1, array['a','b','c','d']),
  (2, array['d','e','f']);

insert into b 
  (id, array2)
values 
  (1, array['x','y','z']), 
  (2, array['m','n','o','p']);

它返回这个结果:

id | elements       
---+----------------
 1 | {a-x,b-y,c-z,d}
 2 | {d-m,e-n,f-o,p}

【讨论】:

    【解决方案2】:

    我认为你想得太远了,试试这个 (SQLFiddle):

    select
       a.id,
       a.array1,
       b.array2,
       array[a.array1[1] || '-' || b.array2[1],
             a.array1[2] || '-' || b.array2[2],
             a.array1[3] || '-' || b.array2[3]] array_concat
    from
       a inner join
       b on b.id = a.id
    ;
    

    【讨论】:

    • 我编辑了问题,问题是每个数组中的元素数量并不总是相同。
    • 你想只加入元素数量相等的数组吗?这很难看,但你可以在 4 和 8 个元素的情况下执行上述操作。
    • 如果是 ['a','b','c','d'] 和 ['x','y','z'] 结果应该是 ['a- x','b-y','c-z','d-'] 或 ['a-x','b-y','c-z','d-null']]
    猜你喜欢
    • 2011-11-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2020-07-05
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多