중첩되지 않은 배열에서 요소의 원래 순서를 유지하는 방법은 무엇입니까?


19

주어진 문자열 :

'PostgreSQL이 훌륭하다고 생각합니다'

해당 문자열에서 찾은 개별 단어를 조작하고 싶습니다. 기본적으로 단어 세부 정보를 얻을 수있는 별도의 요소가 있으며이 사전에서 해당 문자열의 중첩되지 않은 배열에 참여하고 싶습니다.

지금까지 나는 :

select word, meaning, partofspeech
from unnest(string_to_array('I think that PostgreSQL is nifty',' ')) as word
from table t
join dictionary d
on t.word = d.wordname;

이것은 내가하고 싶은 일의 기본을 달성하지만 원래 단어 순서를 유지하지는 않습니다.

관련 질문 :
요소 번호가있는 PostgreSQL unnest ()


하나의 문자열 또는 전체 문자열 테이블 을 처리 하시겠습니까? 그렇다면 테이블에 기본 키가 있습니까?
Erwin Brandstetter

@ErwinBrandstetter 테이블에 하나의 문자열 (기본 키가 있음)
swasheck

답변:


24

WITH ORDINALITY Postgres 9.4 이상

새로운 기능은 이러한 종류의 문제를 단순화합니다. 위의 쿼리는 이제 간단히 다음과 같습니다.

SELECT *
FROM   regexp_split_to_table('I think Postgres is nifty', ' ') WITH ORDINALITY x(word, rn);

또는 테이블에 적용하십시오.

SELECT *
FROM   tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);

세부:

암시 적 LATERAL조인 정보 :

Postgres 9.3 이상 및보다 일반적인 설명

단일 문자열

row_number()요소의 순서를 기억하기 위해 창 기능 을 적용 할 수 있습니다 . 그러나 일반적으로 문자열 의 원래 위치 가 아니라 정렬 순서row_number() OVER (ORDER BY col) 에 따라 숫자를 얻습니다 .

ORDER BY위치를 "있는 그대로" 생략 하기 만하면 됩니다.

SELECT *, row_number() OVER () AS rn
FROM   regexp_split_to_table('I think Postgres is nifty', ' ') AS x(word);

regexp_split_to_table()긴 문자열을 사용하면 성능이 저하됩니다. unnest(string_to_array(...))더 나은 확장 성 :

SELECT *, row_number() OVER () AS rn
FROM   unnest(string_to_array('I think Postgres is nifty', ' ')) AS x(word);

그러나 이것이 정상적으로 작동 하고 간단한 쿼리에서 깨지는 것을 본 적이 없지만 Postgres는 명시 적없이 행 순서에 대해서는 아무것도 주장하지 않습니다 ORDER BY.

원래 문자열에서 요소의 서수 를 보장 하려면 generate_subscript()(@deszo의 주석으로 개선)을 사용하십시오.

SELECT arr[rn] AS word, rn
FROM   (
   SELECT *, generate_subscripts(arr, 1) AS rn
   FROM   string_to_array('I think Postgres is nifty', ' ') AS x(arr)
   ) y;

문자열 표

추가 PARTITION BY id받는 OVER절 ...

데모 테이블 :

CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
  ('I think Postgres is nifty')
 ,('And it keeps getting better');

기본 키ctid 대신 임시로 사용 합니다 . 하나 (또는 고유 한 열 )가있는 경우 대신 사용하십시오.

SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM  (
   SELECT ctid, unnest(string_to_array(string, ' ')) AS word
   FROM   strings
   ) x;

이것은 별개의 ID없이 작동합니다.

SELECT arr[rn] AS word, rn
FROM  (
   SELECT *, generate_subscripts(arr, 1) AS rn
   FROM  (
      SELECT string_to_array(string, ' ') AS arr
      FROM   strings
      ) x
   ) y;

SQL 바이올린.

질문에 대한 답변

SELECT z.arr, z.rn, z.word, d.meaning   -- , partofspeech -- ?
FROM  (
   SELECT *, arr[rn] AS word
   FROM  (
      SELECT *, generate_subscripts(arr, 1) AS rn
      FROM  (
         SELECT string_to_array(string, ' ') AS arr
         FROM   strings
         ) x
      ) y
   ) z
JOIN   dictionary d ON d.wordname = z.word
ORDER  BY z.arr, z.rn;

1
Pg의 기발한 SRF-in-SELECT-list 동작을 활용할 수도 있습니다 SELECT generate_series(1,array_length(word_array,1)), unnest(word_array) FROM ..... 9.3 LATERAL은이 문제에 대한 더 나은 솔루션을 제공 할 수 있습니다.
크레이그 링거

2
하지 않을까요 generate_subscripts(arr, 1)대신 일을 generate_series(1, array_upper(arr, 1))? 명확성을 위해 전자를 선호합니다.
데소

1
@ Erwin depesz 에서이 WITH ORDINALITY 게시물 을 보셨습니까?
잭 더글러스

1
@ JackDouglas : 우리는 금요일에 관련 주제에 대해 토론했습니다 . 나는 대답에 약간을 추가했다.
Erwin Brandstetter

1
"세부 사항"에 대한 링크는 동일한 페이지로 연결됩니다. 혼란 스럽습니다.
와일드 카드
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.