sql >> Databáze >  >> RDS >> PostgreSQL

Je pořadí zachováno po UNION v PostgreSQL?

V zásadě je váš dotaz na začátku nesprávný. Použijte UNION ALL , nikoli UNION nebo byste nesprávně odstranili duplicitní položky. (Není nic, co by říkalo, že stezka nemůže přepínat tam a zpět mezi stejnými e-maily.)

Implementace Postgres pro UNION ALL vrátí hodnoty v připojené sekvenci – pokud to neděláte přidat ORDER BY na konci nebo s výsledkem udělejte cokoli jiného.
Uvědomte si však, že každý SELECT vrátí řádky v libovolném pořadí, pokud není ORDER BY je připojeno. V tabulkách neexistuje přirozený řád.

Totéž ne true pro UNION , který musí zpracovat všechny řádky, aby odstranil případné duplikáty. Existují různé způsoby, jak určit duplikáty, výsledné pořadí řádků závisí na zvoleném algoritmu a je závislé na implementaci a zcela nespolehlivé - pokud opět ORDER BY je připojeno.

Takže místo toho použijte:

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

Chcete-li získat spolehlivé pořadí řazení a „simulovat záznam růstu“, můžete úrovně sledovat takto:

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<>fiddle zde
Staré sqlfiddle

Aside:if old_email není definováno UNIQUE nějakým způsobem můžete získat více cest. Potřebovali byste jedinečný sloupec (nebo kombinaci sloupců), aby byl jednoznačný. Pokud vše ostatní selže, můžete (ab-) použít interní ID n-tice ctid za účelem odlišení stop od sebe. Raději ale použijte vlastní sloupce. (Přidán příklad do houslí.)

Zvažte:



  1. Replikace PostgreSQL pro zotavení po havárii

  2. MySQL Select Top N Rows

  3. Nalezeno 'OR 1=1/* sql injection v mé databázi newsletteru

  4. MySQL / PHP - Najděte dostupné časové úseky