选择整数数组数组的每个第一个元素到数组

时间:2021-04-16 22:58:16

How to select every first element of array of integer arrays to array?
{{1,2,3},{2,15,32},{5,16,14},...} -> {1,2,5,...}

如何选择整数数组的每个第一个元素到数组? {{1,2,3},{2,15,32},{5,16,14},...} - > {1,2,5,...}

3 个解决方案

#1


1  

Since PostgreSQL will allow asking for a slice outside of the array size, and assuming there will never be more than 999 subarrays, we can use this monstrosity

由于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;

You can of course make the constant 999 larger if needed, it is just a random large number I threw in there.

你当然可以根据需要增加999的常数,这只是我投入的一个随机大数字。

The reason why this is so complicated is that if you would use just arr[1:999][1] you would still get a two-dimensional array, but with only the first elements. In this case {{1}, {2}, {5}}. If we use unnest() we can make it into a set, which can then be fed into array_agg() via subselect.

之所以如此复杂,是因为如果你只使用arr [1:999] [1],你仍会得到一个二维数组,但只有第一个元素。在这种情况下{{1},{2},{5}}。如果我们使用unnest(),我们可以将它变成一个集合,然后可以通过subselect将其输入到array_agg()中。

It would be nice to use array_agg(unnest(arr[1:999][1])) but the aggregation function doesn't like sets and I don't know if there is a way to convert it on the fly.

使用array_agg(unexst(arr [1:999] [1]))会很好,但聚合函数不喜欢集合,我不知道是否有办法在运行中转换它。

You can also use the actual array length, but it might cause unnecessary computation

您也可以使用实际的数组长度,但这可能会导致不必要的计算

SELECT unnest(arr[1:array_length(arr, 1)][1]) as arr from data

Note

注意

If the arrays could be unnested by one level, you could just index the arrays and then use array_agg() to convert it back into an array with a lot simpler syntax

如果数组可以被一个级别取消,你可以只索引数组,然后使用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;

The CTE is there just for input data, the actual meat is the array_agg(arr[1]). This will of course work for any number of input arrays.

CTE只用于输入数据,实际的肉是array_agg(arr [1])。这当然适用于任意数量的输入数组。

#2


1  

Given this table:

鉴于此表:

CREATE TEMP TABLE arrtbl (
   arrtbl_id serial PRIMARY KEY
 , arr int[]
);

Sample values:

样本值:

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);

This would do the job for all rows:

这将完成所有行的工作:

SELECT arrtbl_id, array_agg(a) AS a1
FROM   arrtbl t
    ,  unnest(t.arr[-2147483648:2147483647][1]) a
GROUP  BY 1;

Why [-2147483648:2147483647]?

为什么[-2147483648:2147483647]?

Result:

结果:

arrtbl_id | a1
----------+-----------
1         | '{1,2,5}'
2         | '{17,1,16}'

Note that rows with empty / NULL array in arr are dropped from the result.
Also, while the above usually works, rather use this safe syntax:

请注意,arr中的空/ NULL数组的行将从结果中删除。此外,虽然上述通常有效,但请使用以下安全语法:

SELECT arrtbl_id, array_agg(a.a ORDER BY a.ordinality)
FROM   arrtbl t
LEFT   JOIN LATERAL unnest(t.arr[-2147483648:2147483647][1]) WITH ORDINALITY a ON true
GROUP  BY 1;

Result:

结果:

arrtbl_id | a1
----------+-----------
1         | '{1,2,5}'
2         | '{17,1,16}'
3         | null
4         | null

Detailed explanation:

详细说明:

#3


0  

Plpgsql solution:

Plpgsql解决方案:

create or replace function first_elements(arr anyarray)
returns int[] language plpgsql
as $$
declare
    i int;
    res int[];
begin
    for i in 1..array_length(arr, 1) loop
        res = array_append(res, arr[i][1]);
    end loop;
    return res;
end $$;  

with test as (
    select array[array[1,2,3], array[2,15,32], array[5,16,14]] a
    union
    select array[array[101,0], array[102,0]] a
    )
select first_elements(a) from test;

 first_elements
----------------
 {1,2,5}
 {101,102}
(2 rows)    

#1


1  

Since PostgreSQL will allow asking for a slice outside of the array size, and assuming there will never be more than 999 subarrays, we can use this monstrosity

由于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;

You can of course make the constant 999 larger if needed, it is just a random large number I threw in there.

你当然可以根据需要增加999的常数,这只是我投入的一个随机大数字。

The reason why this is so complicated is that if you would use just arr[1:999][1] you would still get a two-dimensional array, but with only the first elements. In this case {{1}, {2}, {5}}. If we use unnest() we can make it into a set, which can then be fed into array_agg() via subselect.

之所以如此复杂,是因为如果你只使用arr [1:999] [1],你仍会得到一个二维数组,但只有第一个元素。在这种情况下{{1},{2},{5}}。如果我们使用unnest(),我们可以将它变成一个集合,然后可以通过subselect将其输入到array_agg()中。

It would be nice to use array_agg(unnest(arr[1:999][1])) but the aggregation function doesn't like sets and I don't know if there is a way to convert it on the fly.

使用array_agg(unexst(arr [1:999] [1]))会很好,但聚合函数不喜欢集合,我不知道是否有办法在运行中转换它。

You can also use the actual array length, but it might cause unnecessary computation

您也可以使用实际的数组长度,但这可能会导致不必要的计算

SELECT unnest(arr[1:array_length(arr, 1)][1]) as arr from data

Note

注意

If the arrays could be unnested by one level, you could just index the arrays and then use array_agg() to convert it back into an array with a lot simpler syntax

如果数组可以被一个级别取消,你可以只索引数组,然后使用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;

The CTE is there just for input data, the actual meat is the array_agg(arr[1]). This will of course work for any number of input arrays.

CTE只用于输入数据,实际的肉是array_agg(arr [1])。这当然适用于任意数量的输入数组。

#2


1  

Given this table:

鉴于此表:

CREATE TEMP TABLE arrtbl (
   arrtbl_id serial PRIMARY KEY
 , arr int[]
);

Sample values:

样本值:

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);

This would do the job for all rows:

这将完成所有行的工作:

SELECT arrtbl_id, array_agg(a) AS a1
FROM   arrtbl t
    ,  unnest(t.arr[-2147483648:2147483647][1]) a
GROUP  BY 1;

Why [-2147483648:2147483647]?

为什么[-2147483648:2147483647]?

Result:

结果:

arrtbl_id | a1
----------+-----------
1         | '{1,2,5}'
2         | '{17,1,16}'

Note that rows with empty / NULL array in arr are dropped from the result.
Also, while the above usually works, rather use this safe syntax:

请注意,arr中的空/ NULL数组的行将从结果中删除。此外,虽然上述通常有效,但请使用以下安全语法:

SELECT arrtbl_id, array_agg(a.a ORDER BY a.ordinality)
FROM   arrtbl t
LEFT   JOIN LATERAL unnest(t.arr[-2147483648:2147483647][1]) WITH ORDINALITY a ON true
GROUP  BY 1;

Result:

结果:

arrtbl_id | a1
----------+-----------
1         | '{1,2,5}'
2         | '{17,1,16}'
3         | null
4         | null

Detailed explanation:

详细说明:

#3


0  

Plpgsql solution:

Plpgsql解决方案:

create or replace function first_elements(arr anyarray)
returns int[] language plpgsql
as $$
declare
    i int;
    res int[];
begin
    for i in 1..array_length(arr, 1) loop
        res = array_append(res, arr[i][1]);
    end loop;
    return res;
end $$;  

with test as (
    select array[array[1,2,3], array[2,15,32], array[5,16,14]] a
    union
    select array[array[101,0], array[102,0]] a
    )
select first_elements(a) from test;

 first_elements
----------------
 {1,2,5}
 {101,102}
(2 rows)