Postgres 9.4 이상
사용 WITH ORDINALITY
설정을 반환하는 기능 :
FROM
절의 함수에 접미사가 붙으면 1부터 시작하여 함수 출력의 각 행에 대해 1 씩 증가 WITH ORDINALITY
하는
bigint
열이 출력에 추가됩니다. 이것은 unnest()
.
LATERAL
pg 9.3+ 의 기능 과 결합하고 pgsql-hackers 의이 스레드에 따르면 위의 쿼리는 이제 다음과 같이 작성할 수 있습니다.
SELECT t.id, a.elem, a.nr
FROM tbl AS t
LEFT JOIN LATERAL unnest(string_to_array(t.elements, ','))
WITH ORDINALITY AS a(elem, nr) ON TRUE;
LEFT JOIN ... ON TRUE
오른쪽에있는 테이블 표현식이 행을 반환하지 않더라도 왼쪽 테이블의 모든 행을 유지합니다. 그것이 문제가되지 않는다면이 동등하고 덜 장황한 형태를 암시 적으로 사용할 수 있습니다 CROSS JOIN LATERAL
.
SELECT t.id, a.elem, a.nr
FROM tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr);
또는 실제 배열 ( arr
배열 열)을 기반으로하는 경우 더 간단합니다 .
SELECT t.id, a.elem, a.nr
FROM tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr);
또는 최소한의 구문으로 :
SELECT id, a, ordinality
FROM tbl, unnest(arr) WITH ORDINALITY a;
a
자동으로 테이블 및 열 별칭입니다. 추가 된 순서 열의 기본 이름은입니다 ordinality
. 그러나 명시 적 열 별칭 및 테이블 한정 열을 추가하는 것이 더 좋습니다 (안전하고 깔끔함).
Postgres 8.4-9.3
함께 row_number() OVER (PARTITION BY id ORDER BY elem)
사용하면 정렬 순서가 아닌의 서수에 따라 번호를 얻을 원래 순서 위 문자열이다.
간단히 생략 할 수 있습니다 ORDER BY
.
SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t;
이것이 정상적으로 작동하고 간단한 쿼리에서 실패하는 것을 본 적이 없지만 PostgreSQL은 ORDER BY
. 구현 세부 사항으로 인해 작동합니다.
공백으로 구분 된 문자열 에서 요소의 서수 를 보장 하려면 다음을 수행하십시오.
SELECT id, arr[nr] AS elem, nr
FROM (
SELECT *, generate_subscripts(arr, 1) AS nr
FROM (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
) sub;
또는 실제 배열을 기반으로하는 경우 더 간단합니다 .
SELECT id, arr[nr] AS elem, nr
FROM (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t;
dba.SE 관련 답변 :
Postgres 8.1-8.4
이러한 기능 중에 아직 사용할 수 없습니다 : RETURNS TABLE
, generate_subscripts()
, unnest()
, array_length()
. 그러나 이것은 작동합니다.
CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
RETURNS SETOF record
LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1
FROM generate_series(array_lower($1,1), array_upper($1,1)) i';
특히 배열 인덱스는 요소의 서수 위치와 다를 수 있습니다. 확장 된 기능 이있는이 데모를 고려하십시오 .
CREATE FUNCTION f_unnest_ord_idx(anyarray, OUT val anyelement, OUT ordinality int, OUT idx int)
RETURNS SETOF record
LANGUAGE sql IMMUTABLE AS
'SELECT $1[i], i - array_lower($1,1) + 1, i
FROM generate_series(array_lower($1,1), array_upper($1,1)) i';
SELECT id, arr, (rec).*
FROM (
SELECT *, f_unnest_ord_idx(arr) AS rec
FROM (VALUES (1, '{a,b,c}'::text[])
, (2, '[5:7]={a,b,c}')
, (3, '[-9:-7]={a,b,c}')
) t(id, arr)
) sub;
id | arr | val | ordinality | idx
1 | {a,b,c} | a | 1 | 1
1 | {a,b,c} | b | 2 | 2
1 | {a,b,c} | c | 3 | 3
2 | [5:7]={a,b,c} | a | 1 | 5
2 | [5:7]={a,b,c} | b | 2 | 6
2 | [5:7]={a,b,c} | c | 3 | 7
3 | [-9:-7]={a,b,c} | a | 1 | -9
3 | [-9:-7]={a,b,c} | b | 2 | -8
3 | [-9:-7]={a,b,c} | c | 3 | -7
비교: