Select 整数数组数组的每个第一个元素到数组
Select every first element of array of integer arrays to array
如何select整型数组数组的每个第一个元素到数组中?
{{1,2,3},{2,15,32},{5,16,14},...}
-> {1,2,5,...}
由于 PostgreSQL 允许请求超出数组大小的切片,并且假设永远不会超过 999 个子数组,我们可以使用这个怪物
WITH data AS (
SELECT array[array[1,2,3], array[2,15,32], array[5,16,14]] as arr)
SELECT array_agg(arr)
FROM (SELECT unnest(arr[1:999][1]) as arr from data) data2;
如果需要,您当然可以将常量 999 变大,它只是我随机输入的一个大数。
之所以如此复杂,是因为如果您只使用 arr[1:999][1]
,您仍然会得到一个二维数组,但只有第一个元素。在这种情况下 {{1}, {2}, {5}}
。如果我们使用 unnest()
,我们可以将其组成一个集合,然后可以通过子选择将其输入 array_agg()
。
使用array_agg(unnest(arr[1:999][1]))
会很好,但是聚合函数不喜欢集合,我不知道是否有办法即时转换它。
也可以使用实际的数组长度,但可能会造成不必要的计算
SELECT unnest(arr[1:array_length(arr, 1)][1]) as arr from data
备注
如果数组可以取消一级嵌套,您可以只对数组进行索引,然后使用 array_agg()
将其转换回具有更简单语法的数组
WITH data AS
(SELECT array[1,2,3] as arr
UNION ALL SELECT array[2,15,32] as arr
UNION ALL SELECT array[5,16,14] as arr)
SELECT array_agg(arr[1]) from data;
CTE 仅用于输入数据,实际内容是 array_agg(arr[1])
。这当然适用于任意数量的输入数组。
鉴于此 table 和值:
CREATE TABLE arrtbl (
arrtbl_id serial PRIMARY KEY
, arr int[]
);
INSERT INTO arrtbl (arr) VALUES
('{{1,2,3},{2,15,32},{5,16,14}}')
, ('{{17,22},{1,15},{16,14}}') -- dimensions can vary across rows!
, ('{}')
, (null);
这将完成所有行的工作:
SELECT arrtbl_id, array_agg(a) AS a1
FROM arrtbl t
, unnest(t.arr[:][1]) a
GROUP BY 1;
为什么 [:]
?
- Normalize array subscripts for 1-dimensional array so they start with 1
所以只有在可以有非标准数组下标的情况下。
结果:
arrtbl_id | a1
----------+-----------
1 | '{1,2,5}'
2 | '{17,1,16}'
arr
中具有空/NULL 数组的行从结果中删除。
此外,虽然上述通常有效,但请使用此 安全语法 :
SELECT arrtbl_id, array_agg(a.a ORDER BY a.ordinality)
FROM arrtbl t
LEFT JOIN LATERAL unnest(t.arr[:][1]) WITH ORDINALITY a ON true
GROUP BY 1;
子查询中相同的、更明确的和单一的排序通常更快:
SELECT arrtbl_id, array_agg(elem)
FROM (
SELECT t.arrtbl_id, a.elem
FROM arrtbl t
LEFT JOIN LATERAL unnest(t.arr[:][1]) WITH ORDINALITY a(elem, ord) ON true
ORDER BY t.arrtbl_id, a.ord
) sub
GROUP BY 1
ORDER BY 1;
结果:
arrtbl_id | a1
----------+-----------
1 | '{1,2,5}'
2 | '{17,1,16}'
3 | null
4 | null
db<>fiddle here
详细解释:
- PostgreSQL unnest() with element number
如何select整型数组数组的每个第一个元素到数组中?
{{1,2,3},{2,15,32},{5,16,14},...}
-> {1,2,5,...}
由于 PostgreSQL 允许请求超出数组大小的切片,并且假设永远不会超过 999 个子数组,我们可以使用这个怪物
WITH data AS (
SELECT array[array[1,2,3], array[2,15,32], array[5,16,14]] as arr)
SELECT array_agg(arr)
FROM (SELECT unnest(arr[1:999][1]) as arr from data) data2;
如果需要,您当然可以将常量 999 变大,它只是我随机输入的一个大数。
之所以如此复杂,是因为如果您只使用 arr[1:999][1]
,您仍然会得到一个二维数组,但只有第一个元素。在这种情况下 {{1}, {2}, {5}}
。如果我们使用 unnest()
,我们可以将其组成一个集合,然后可以通过子选择将其输入 array_agg()
。
使用array_agg(unnest(arr[1:999][1]))
会很好,但是聚合函数不喜欢集合,我不知道是否有办法即时转换它。
也可以使用实际的数组长度,但可能会造成不必要的计算
SELECT unnest(arr[1:array_length(arr, 1)][1]) as arr from data
备注
如果数组可以取消一级嵌套,您可以只对数组进行索引,然后使用 array_agg()
将其转换回具有更简单语法的数组
WITH data AS
(SELECT array[1,2,3] as arr
UNION ALL SELECT array[2,15,32] as arr
UNION ALL SELECT array[5,16,14] as arr)
SELECT array_agg(arr[1]) from data;
CTE 仅用于输入数据,实际内容是 array_agg(arr[1])
。这当然适用于任意数量的输入数组。
鉴于此 table 和值:
CREATE TABLE arrtbl (
arrtbl_id serial PRIMARY KEY
, arr int[]
);
INSERT INTO arrtbl (arr) VALUES
('{{1,2,3},{2,15,32},{5,16,14}}')
, ('{{17,22},{1,15},{16,14}}') -- dimensions can vary across rows!
, ('{}')
, (null);
这将完成所有行的工作:
SELECT arrtbl_id, array_agg(a) AS a1
FROM arrtbl t
, unnest(t.arr[:][1]) a
GROUP BY 1;
为什么 [:]
?
- Normalize array subscripts for 1-dimensional array so they start with 1
所以只有在可以有非标准数组下标的情况下。
结果:
arrtbl_id | a1
----------+-----------
1 | '{1,2,5}'
2 | '{17,1,16}'
arr
中具有空/NULL 数组的行从结果中删除。
此外,虽然上述通常有效,但请使用此 安全语法 :
SELECT arrtbl_id, array_agg(a.a ORDER BY a.ordinality)
FROM arrtbl t
LEFT JOIN LATERAL unnest(t.arr[:][1]) WITH ORDINALITY a ON true
GROUP BY 1;
子查询中相同的、更明确的和单一的排序通常更快:
SELECT arrtbl_id, array_agg(elem)
FROM (
SELECT t.arrtbl_id, a.elem
FROM arrtbl t
LEFT JOIN LATERAL unnest(t.arr[:][1]) WITH ORDINALITY a(elem, ord) ON true
ORDER BY t.arrtbl_id, a.ord
) sub
GROUP BY 1
ORDER BY 1;
结果:
arrtbl_id | a1
----------+-----------
1 | '{1,2,5}'
2 | '{17,1,16}'
3 | null
4 | null
db<>fiddle here
详细解释:
- PostgreSQL unnest() with element number