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 (
SELECT regexp_split_to_table('I think postgres is nifty', ' ') AS word
) x;
regexp_split_to_table()
長い文字列ではパフォーマンスが低下します。 unnest(string_to_array(...))
より良いスケール:
SELECT *, row_number() OVER () AS rn
FROM (
SELECT unnest(string_to_array('I think postgres is nifty', ' ')) AS word
) x;
ただし、これは通常は機能し、単純なクエリで破損することは一度もありませんが、PostgreSQLは明示的なORDER BY
。
元の文字列の要素の序数を保証するには、generate_subscript()
(@ deszoによるコメントで改善された)を使用します。
SELECT arr[rn] AS word, rn
FROM (
SELECT *, generate_subscripts(arr, 1) AS rn
FROM (
SELECT string_to_array('I think postgres is nifty', ' ') AS arr
) x
) 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
アドホック代替として使用します。1つ(または一意の列)がある場合は、代わりにそれを使用します。
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;