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 LATERAL
unió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 BY
para 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 id
a la OVER
clá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 ctid
como 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;