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