Maison > base de données > tutoriel mysql > Comment obtenir le numéro d'élément lors de l'utilisation de la fonction unnest() de PostgreSQL ?

Comment obtenir le numéro d'élément lors de l'utilisation de la fonction unnest() de PostgreSQL ?

Linda Hamilton
Libérer: 2025-01-23 04:25:13
original
311 Les gens l'ont consulté

How to Get the Element Number When Using PostgreSQL's unnest() Function?

PostgreSQL unnest() Fonctions et numéros d'éléments

Question

Lorsque vous rencontrez une colonne contenant des valeurs délimitées, la fonction unnest() fournit un moyen d'extraire ces valeurs :

myTable
id | elements
---+------------
1  |ab,cd,efg,hi
2  |jk,lm,no,pq
3  |rstuv,wxyz

select id, unnest(string_to_array(elements, ',')) AS elem
from myTable

id | elem
---+-----
1  | ab
1  | cd
1  | efg
1  | hi
2  | jk
...
Copier après la connexion
Copier après la connexion

Cependant, vous souhaiterez peut-être également inclure le numéro de l'élément, dans le format suivant :

id | elem | nr
---+------+---
1  | ab   | 1
1  | cd   | 2
1  | efg  | 3
1  | hi   | 4
2  | jk   | 1
...
Copier après la connexion
Copier après la connexion

Le but ultime est d'obtenir la position d'origine de chaque élément dans la chaîne source sans utiliser de fonctions de fenêtre comme row_number() ou rank() car ces fonctions renvoient toujours 1, probablement parce que tous les éléments sont dans la même ligne de la source tableau.

Solution

PostgreSQL 14 ou supérieur

Pour les chaînes séparées par des virgules, utilisez string_to_table() au lieu de unnest(string_to_array()) :

SELECT t.id, a.elem, a.nr
FROM   tbl t
LEFT   JOIN LATERAL string_to_table(t.elements, ',') WITH ORDINALITY AS a(elem, nr) ON true
Copier après la connexion
Copier après la connexion

Démo

PostgreSQL 9.4 ou supérieur

Pour les fonctions qui renvoient une collection, utilisez WITH ORDINALITY :

SELECT t.id, a.elem, a.nr
FROM   tbl AS t
LEFT   JOIN LATERAL unnest(string_to_array(t.elements, ',')) WITH ORDINALITY AS a(elem, nr) ON true
Copier après la connexion

LEFT JOIN ... ON true Garantit que toutes les lignes du tableau de gauche sont conservées, que l'expression du tableau de droite renvoie ou non des lignes.

Alternativement, puisque LEFT JOIN ... ON true conserve toutes les lignes, une version plus concise de la requête peut être utilisée :

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(string_to_array(t.elements, ',')) WITH ORDINALITY a(elem, nr)
Copier après la connexion

Pour les tableaux réels (arr sont des colonnes de tableau), une forme plus concise peut être utilisée :

SELECT t.id, a.elem, a.nr
FROM   tbl t, unnest(t.arr) WITH ORDINALITY a(elem, nr)
Copier après la connexion

Pour plus de simplicité, vous pouvez utiliser les noms de colonnes par défaut :

SELECT id, a, ordinality
FROM   tbl, unnest(arr) WITH ORDINALITY a
Copier après la connexion

Peut être encore simplifié :

SELECT * FROM tbl, unnest(arr) WITH ORDINALITY a
Copier après la connexion

Ce formulaire final renvoie toutes les colonnes de tbl. Bien entendu, la spécification explicite des alias de colonnes et des colonnes qualifiées de table peut améliorer la clarté.

a est utilisé à la fois comme alias de table et comme alias de colonne (pour la première colonne), et le nom par défaut de la colonne ordinale ajoutée est ordinality.

PostgreSQL 8.4 - 9.3

Utilisez row_number() OVER (PARTITION BY id ORDER BY elem) pour obtenir des nombres en fonction de l'ordre de tri (plutôt que de la position ordinale) :

SELECT *, row_number() OVER (PARTITION by id) AS nr
FROM  (SELECT id, regexp_split_to_table(elements, ',') AS elem FROM tbl) t
Copier après la connexion

Bien que cela fonctionne généralement et qu'aucun échec n'ait été observé dans les requêtes simples, PostgreSQL ne garantit pas l'ordre des lignes sans ORDER BY. Le comportement actuel est le résultat des détails de mise en œuvre.

Pour s'assurer que le numéro de série séparé par des espaces des éléments de la chaîne  :

SELECT id, arr[nr] AS elem, nr
FROM  (
   SELECT *, generate_subscripts(arr, 1) AS nr
   FROM  (SELECT id, string_to_array(elements, ' ') AS arr FROM tbl) t
   ) sub
Copier après la connexion

Pour les tableaux réels, une version plus simple peut être utilisée :

SELECT id, arr[nr] AS elem, nr
FROM  (SELECT *, generate_subscripts(arr, 1) AS nr FROM tbl) t
Copier après la connexion

PostgreSQL 8.1 - 8.4

Étant donné que certaines fonctionnalités de PostgreSQL 8.1 à 8.4 manquent, telles que RETURNS TABLE, generate_subscripts(), unnest() et array_length(), une fonction SQL personnalisée nommée f_unnest_ord peut être utilisée :

CREATE FUNCTION f_unnest_ord(anyarray, OUT val anyelement, OUT ordinality integer)
  RETURNS SETOF record
  LANGUAGE sql IMMUTABLE AS
'SELECT [i], i - array_lower(,1) + 1
 FROM   generate_series(array_lower(,1), array_upper(,1)) i'
Copier après la connexion

La fonction modifiée est la suivante :

myTable
id | elements
---+------------
1  |ab,cd,efg,hi
2  |jk,lm,no,pq
3  |rstuv,wxyz

select id, unnest(string_to_array(elements, ',')) AS elem
from myTable

id | elem
---+-----
1  | ab
1  | cd
1  | efg
1  | hi
2  | jk
...
Copier après la connexion
Copier après la connexion

Cette fonction d'extension f_unnest_ord_idx renvoie des idx colonnes supplémentaires. Comparez :

id | elem | nr
---+------+---
1  | ab   | 1
1  | cd   | 2
1  | efg  | 3
1  | hi   | 4
2  | jk   | 1
...
Copier après la connexion
Copier après la connexion

Sortie

SELECT t.id, a.elem, a.nr
FROM   tbl t
LEFT   JOIN LATERAL string_to_table(t.elements, ',') WITH ORDINALITY AS a(elem, nr) ON true
Copier après la connexion
Copier après la connexion

Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!

Déclaration de ce site Web
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn
Derniers articles par auteur
Tutoriels populaires
Plus>
Derniers téléchargements
Plus>
effets Web
Code source du site Web
Matériel du site Web
Modèle frontal