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 LATERALVerknü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 idauf die OVERKlausel ...
Demo-Tabelle:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think postgres is nifty')
,('And it keeps getting better');
Ich benutze ctidals 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;