WITH ORDINALITY
dans Postgres 9.4 ou version ultérieure
La nouvelle fonctionnalité simplifie cette classe de problèmes. La requête ci-dessus peut maintenant simplement être:
SELECT *
FROM regexp_split_to_table('I think Postgres is nifty', ' ') WITH ORDINALITY x(word, rn);
Ou, appliqué à une table:
SELECT *
FROM tbl t, regexp_split_to_table(t.my_column, ' ') WITH ORDINALITY x(word, rn);
Détails:
À propos de la LATERAL
jointure implicite :
Postgres 9.3 ou plus ancien - et explication plus générale
Pour une seule chaîne
Vous pouvez appliquer la fonction de fenêtre row_number()
pour mémoriser l'ordre des éléments. Cependant, avec l'habituel, row_number() OVER (ORDER BY col)
vous obtenez des nombres selon l' ordre de tri , pas la position d'origine dans la chaîne.
Vous pouvez simplement omettre ORDER BY
d'obtenir le poste "tel quel":
SELECT *, row_number() OVER () AS rn
FROM regexp_split_to_table('I think Postgres is nifty', ' ') AS x(word);
Performance des regexp_split_to_table()
dégradés avec des cordes longues. unnest(string_to_array(...))
se balance mieux:
SELECT *, row_number() OVER () AS rn
FROM unnest(string_to_array('I think Postgres is nifty', ' ')) AS x(word);
Cependant, bien que cela fonctionne normalement et que je ne l'ai jamais vu casser dans des requêtes simples, Postgres n'affirme rien quant à l'ordre des lignes sans explicite ORDER BY
.
Pour garantir le nombre ordinal d'éléments dans la chaîne d'origine, utilisez generate_subscript()
(amélioré avec le commentaire 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;
Pour une table de cordes
Ajouter PARTITION BY id
à la OVER
clause ...
Table de démonstration:
CREATE TEMP TABLE strings(string text);
INSERT INTO strings VALUES
('I think Postgres is nifty')
,('And it keeps getting better');
J'utilise ctid
comme substitut ad hoc pour une clé primaire . Si vous en avez une (ou une colonne unique ), utilisez-la à la place.
SELECT *, row_number() OVER (PARTITION BY ctid) AS rn
FROM (
SELECT ctid, unnest(string_to_array(string, ' ')) AS word
FROM strings
) x;
Cela fonctionne sans aucun identifiant distinct:
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.
Réponse à la question
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;