WITH ORDINALITY
w Postgres 9.4 lub nowszym
Nowa funkcja upraszcza tę klasę problemów. Powyższe zapytanie może teraz być po prostu:
SELECT *
FROM regexp_split_to_table('I think Postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
Lub zastosowane do tabeli:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Detale:
Informacje o niejawnym LATERAL
połączeniu:
Postgres 9.3 lub starszy - i bardziej ogólne wyjaśnienie
Dla pojedynczego ciągu
Możesz zastosować funkcję okna, row_number()
aby zapamiętać kolejność elementów. Jednak w zwykłym przypadku row_number() OVER (ORDER BY col)
otrzymujesz liczby zgodnie z kolejnością sortowania , a nie pierwotną pozycję w ciągu.
Możesz po prostu pominąć, ORDER BY
aby uzyskać pozycję „jak jest”:
SELECT *, row_number() OVER () AS rn
FROM regexp_split_to_table('I think Postgres is nifty', ' ') AS x(word);
Wydajność regexp_split_to_table()
degradacji z długimi łańcuchami. unnest(string_to_array(...))
skaluje się lepiej:
SELECT *, row_number() OVER () AS rn
FROM unnest(string_to_array('I think Postgres is nifty', ' ')) AS x(word);
Jednak, chociaż normalnie działa to i nigdy nie widziałem, aby łamał się w prostych zapytaniach, Postgres nie zapewnia niczego o kolejności wierszy bez wyraźnego ORDER BY
.
Aby zagwarantować liczbę porządkową elementów w oryginalnym łańcuchu, użyj generate_subscript()
(poprawione komentarzem @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;
Dla tabeli ciągów znaków
Dodaj PARTITION BY id
do OVER
klauzuli ...
Tabela demo:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think Postgres is nifty')
,('And it keeps getting better');
Używam ctid
jako ad-hoc zamiennika klucza podstawowego . Jeśli masz jedną (lub dowolną unikalną kolumnę ), użyj jej zamiast tego.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
To działa bez wyraźnego 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 Fiddle.
Odpowiedz na pytanie
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;