WITH ORDINALITY
in Postgres 9.4 oder später
Das neue Feature vereinfacht diese Art von Problemen. Die obige Abfrage kann nun einfach sein:
SELECT *
FROM regexp_split_to_table('I think postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
Oder auf eine Tabelle angewendet:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Einzelheiten:
Über die implizite LATERAL
Verknüpfung:
Postgres 9.3 oder älter - und allgemeinere Erklärung
Für eine einzelne Zeichenfolge
Sie können die Fensterfunktion anwenden row_number()
, um die Reihenfolge der Elemente zu speichern. Mit dem üblichen row_number() OVER (ORDER BY col)
Verfahren erhalten Sie jedoch Zahlen in der Reihenfolge der Sortierung , nicht die ursprüngliche Position in der Zeichenfolge.
Sie könnten versuchen, einfach das wegzulassen ORDER BY
, um die Position "wie sie ist" zu erhalten:
SELECT *, row_number() OVER () AS rn
FROM (
SELECT regexp_split_to_table('I think postgres is nifty', ' ') AS word
) x;
Leistung regexp_split_to_table()
degradiert mit langen Strings. unnest(string_to_array(...))
skaliert besser:
SELECT *, row_number() OVER () AS rn
FROM (
SELECT unnest(string_to_array('I think postgres is nifty', ' ')) AS word
) x;
Während dies normalerweise funktioniert und ich noch nie bei einfachen Abfragen einen Bruch gesehen habe, behauptet PostgreSQL nichts in Bezug auf die Reihenfolge der Zeilen ohne einen expliziten ORDER BY
.
Um die Ordnungszahl der Elemente in der Originalzeichenfolge zu gewährleisten , verwenden Sie generate_subscript()
(verbessert mit dem Kommentar von @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;
Für eine Streichertabelle
In PARTITION BY id
auf die OVER
Klausel ...
Demo-Tabelle:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think postgres is nifty')
,('And it keeps getting better');
Ich benutze ctid
als Ad-hoc-Ersatz für einen Primärschlüssel . Wenn Sie eine (oder eine eindeutige) Spalte haben, verwenden Sie diese stattdessen.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
Dies funktioniert ohne eindeutige 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-Geige.
Antwort auf Frage
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;