요소 번호가있는 PostgreSQL unnest ()
분리 된 값이있는 열이있는 경우 다음 unnest()
함수를 사용할 수 있습니다 .
myTable
id | elements
---+------------
1 |ab,cd,efg,hi
2 |jk,lm,no,pq
3 |rstuv,wxyz
select id, unnest(string_to_array(elements, ',')) AS elem
from myTable
id | elem
---+-----
1 | ab
1 | cd
1 | efg
1 | hi
2 | jk
...
요소 번호를 어떻게 포함시킬 수 있습니까? 즉 :
id | elem | nr
---+------+---
1 | ab | 1
1 | cd | 2
1 | efg | 3
1 | hi | 4
2 | jk | 1
...
소스 문자열에서 각 요소 의 원래 위치 를 원합니다 . 나는 윈도우 함수 (함께 시도했다 row_number()
, rank()
등)하지만 난 항상 얻을 1
. 소스 테이블의 동일한 행에 있기 때문일까요?
나는 그것이 나쁜 테이블 디자인이라는 것을 알고 있습니다. 내 것이 아니에요. 그냥 고치려고하는 거에요.
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[]) -- short for: '[1:3]={a,b,c}'
, (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
비교:
시험:
select v.*, row_number() over (partition by id order by elem) rn from
(select
id,
unnest(string_to_array(elements, ',')) AS elem
from myTable) v
첨자 생성 함수를 사용합니다 .
http://www.postgresql.org/docs/current/static/functions-srf.html#FUNCTIONS-SRF-SUBSCRIPTS
예를 들면 :
SELECT
id
, elements[i] AS elem
, i AS nr
FROM
( SELECT
id
, elements
, generate_subscripts(elements, 1) AS i
FROM
( SELECT
id
, string_to_array(elements, ',') AS elements
FROM
myTable
) AS foo
) bar
;
더 간단하게 :
SELECT
id
, unnest(elements) AS elem
, generate_subscripts(elements, 1) AS nr
FROM
( SELECT
id
, string_to_array(elements, ',') AS elements
FROM
myTable
) AS foo
;
요소의 순서가 중요하지 않은 경우
select
id, elem, row_number() over (partition by id) as nr
from (
select
id,
unnest(string_to_array(elements, ',')) AS elem
from myTable
) a
unnest2()
운동으로
Older versions before pg v8.4 need a user-defined unnest()
. We can adapt this old function to return elements with an index:
CREATE FUNCTION unnest2(anyarray)
RETURNS TABLE(v anyelement, i integer) AS
$BODY$
SELECT $1[i], i
FROM generate_series(array_lower($1,1),
array_upper($1,1)) i;
$BODY$ LANGUAGE sql IMMUTABLE;
참고URL : https://stackoverflow.com/questions/8760419/postgresql-unnest-with-element-number
'programing' 카테고리의 다른 글
iPhone XCode-앱 아이콘 아래 제목을 변경하는 방법 (0) | 2020.11.10 |
---|---|
자리 표시 자와 대체 개체를 사용하여 JavaScript 문자열 형식을 지정 하시겠습니까? (0) | 2020.11.10 |
Sublime Text 2에 대한 Sass 지원? (0) | 2020.11.10 |
margin-top 작동하지 않음 clear : both (0) | 2020.11.08 |
내 장고 관리 사이트에 CSS 스타일이없는 이유 (0) | 2020.11.08 |