在联接的 table PostgreSQL 上连接数组元素
Concatenate array elements on a joined table PostgreSQL
如果我有这样的查询,是否可以进行 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
;
编辑:
这只适用于一个 table:
SELECT array_agg(el1||el2)
FROM unnest(ARRAY['a','b','c'], ARRAY['d','e','f']) el (el1, el2);
++感谢https://whosebug.com/users/1463595/%D0%9D%D0%9B%D0%9E
编辑:
我找到了一个非常接近的解决方案,但是一旦数组之间的连接完成,它就会混淆一些中间值,尽管如此,我仍然需要一个完美的解决方案...
我现在使用的方法是:
1) 在 2 个独立的基础上创建一个 table
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;
我觉得你想多了,试试这个 (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
;
像这样。
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']);
它returns这个结果:
id | elements
---+----------------
1 | {a-x,b-y,c-z,d}
2 | {d-m,e-n,f-o,p}
如果我有这样的查询,是否可以进行 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
;
编辑:
这只适用于一个 table:
SELECT array_agg(el1||el2)
FROM unnest(ARRAY['a','b','c'], ARRAY['d','e','f']) el (el1, el2);
++感谢https://whosebug.com/users/1463595/%D0%9D%D0%9B%D0%9E
编辑:
我找到了一个非常接近的解决方案,但是一旦数组之间的连接完成,它就会混淆一些中间值,尽管如此,我仍然需要一个完美的解决方案...
我现在使用的方法是:
1) 在 2 个独立的基础上创建一个 table 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;
我觉得你想多了,试试这个 (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
;
像这样。
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']);
它returns这个结果:
id | elements
---+----------------
1 | {a-x,b-y,c-z,d}
2 | {d-m,e-n,f-o,p}