WITH ORDINALITY
in Postgres 9.4 o successivo
La nuova funzionalità semplifica questa classe di problemi. La query sopra può ora essere semplicemente:
SELECT *
FROM regexp_split_to_table('I think Postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
Oppure, applicato a una tabella:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Dettagli:
Informazioni sul LATERAL
join implicito :
Postgres 9.3 o precedente - e spiegazione più generale
Per una singola stringa
È possibile applicare la funzione finestra row_number()
per ricordare l'ordine degli elementi. Tuttavia, con il solito row_number() OVER (ORDER BY col)
ottieni numeri in base all'ordinamento , non alla posizione originale nella stringa.
Si potrebbe semplicemente omettere ORDER BY
di ottenere la posizione "così com'è":
SELECT *, row_number() OVER () AS rn
FROM regexp_split_to_table('I think Postgres is nifty', ' ') AS x(word);
Prestazioni di regexp_split_to_table()
degrado con corde lunghe. unnest(string_to_array(...))
scala meglio:
SELECT *, row_number() OVER () AS rn
FROM unnest(string_to_array('I think Postgres is nifty', ' ')) AS x(word);
Tuttavia, mentre normalmente funziona e non l'ho mai visto interrompere in semplici query, Postgres non afferma nulla sull'ordine delle righe senza un esplicito ORDER BY
.
Per garantire numeri ordinali di elementi nella stringa originale, utilizzaregenerate_subscript()
(migliorato con il commento di @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;
Per una tabella di stringhe
Inserisci PARTITION BY id
alla OVER
clausola ...
Tabella demo:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think Postgres is nifty')
,('And it keeps getting better');
Uso ctid
come sostituto ad-hoc di una chiave primaria . Se ne hai una (o una colonna unica ), usala invece.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
Questo funziona senza alcun ID distinti:
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.
Rispondi alla domanda
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;