WITH ORDINALITY en Postgres 9.4 o posterior
La nueva característica simplifica esta clase de problemas. La consulta anterior ahora puede ser simplemente:
SELECT *
FROM regexp_split_to_table('I think Postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
O, aplicado a una tabla:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Detalles:
Sobre la LATERALunión implícita :
Postgres 9.3 o anterior - y una explicación más general
Para una sola cadena
Puede aplicar la función de ventana row_number()para recordar el orden de los elementos. Sin embargo, con lo habitual row_number() OVER (ORDER BY col)se obtienen números según el orden de clasificación , no la posición original en la cadena.
Simplemente puede omitir ORDER BYpara obtener la posición "tal cual":
SELECT *, row_number() OVER () AS rn
FROM regexp_split_to_table('I think Postgres is nifty', ' ') AS x(word);
Rendimiento de regexp_split_to_table()degrada con cuerdas largas. unnest(string_to_array(...))escala mejor:
SELECT *, row_number() OVER () AS rn
FROM unnest(string_to_array('I think Postgres is nifty', ' ')) AS x(word);
Sin embargo, aunque esto normalmente funciona y nunca lo he visto romperse en consultas simples, Postgres no afirma nada en cuanto al orden de las filas sin un explícito ORDER BY.
Para garantizar números ordinales de elementos en la cadena original, use generate_subscript()(mejorado con comentarios de @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;
Para una mesa de cuerdas
Agregar PARTITION BY ida la OVERcláusula ...
Tabla de demostración:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think Postgres is nifty')
,('And it keeps getting better');
Lo uso ctidcomo sustituto ad-hoc para una clave primaria . Si tiene una (o una columna única ), úsela.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
Esto funciona sin ninguna identificación distinta:
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.
Respuesta a la pregunta
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;