PostgreSQL
 sql >> Base de données >  >> RDS >> PostgreSQL

L'ordre est-il conservé après UNION dans PostgreSQL ?

Fondamentalement, votre requête est incorrecte pour commencer. Utilisez UNION ALL , pas UNION ou vous supprimeriez par erreur les entrées en double. (Rien ne dit que le parcours ne peut pas basculer entre les mêmes e-mails.)

L'implémentation Postgres pour UNION ALL renvoie les valeurs dans la séquence telles qu'elles sont ajoutées - tant que vous ne le faites pas ajouter ORDER BY à la fin ou faire quoi que ce soit d'autre avec le résultat.
Sachez cependant que chaque SELECT renvoie les lignes dans un ordre arbitraire sauf si ORDER BY est annexé. Il n'y a pas d'ordre naturel dans les tableaux.

La même chose n'est pas vrai pour UNION , qui doit traiter toutes les lignes pour supprimer les éventuels doublons. Il existe différentes façons de déterminer les doublons, l'ordre résultant des lignes dépend de l'algorithme choisi et dépend de l'implémentation et n'est absolument pas fiable - à moins, encore une fois, ORDER BY est ajouté.

Alors utilisez à la place :

SELECT * FROM iter1
UNION ALL  -- union all!
SELECT * FROM iter2;

Pour obtenir un ordre de tri fiable et "simuler le record de croissance", vous pouvez suivre les niveaux comme ceci :

WITH RECURSIVE all_emails AS (
   SELECT  *, 1 AS lvl
   FROM    audit_trail
   WHERE   old_email = '[email protected]'

   UNION ALL  -- union all!
   SELECT t.*, a.lvl + 1
   FROM   all_emails  a
   JOIN   audit_trail t ON t.old_email = a.new_email
)
TABLE  all_emails
ORDER  BY lvl;

db<>violon ici
Ancien sqlfiddle

A part :si old_email n'est pas défini UNIQUE d'une certaine manière, vous pouvez obtenir plusieurs pistes. Vous auriez besoin d'une colonne unique (ou d'une combinaison de colonnes) pour la garder sans ambiguïté. Si tout le reste échoue, vous pouvez (ab-)utiliser l'ID de tuple interne ctid dans le but de différencier les sentiers. Mais vous devriez plutôt utiliser vos propres colonnes. (Exemple ajouté dans le violon.)

Considérez :