V SQL, UNION
klauzule zřetězí výsledky dvou dotazů do jediné sady výsledků.
Můžete použít UNION
klauzule s nebo bez ALL
argument:
UNION ALL
– Zahrnuje duplikáty.UNION
– Nezahrnuje duplikáty.
Níže je uvedeno několik základních příkladů, které demonstrují, jak to funguje.
Ukázkové tabulky
Předpokládejme, že máme dvě tabulky:Cats
a Dogs
Cats
+---------+-----------+ | CatId | CatName | |---------+-----------| | 1 | Meow | | 2 | Fluffy | | 3 | Scratch | +---------+-----------+
Dogs
+---------+-----------+ | DogId | DogName | |---------+-----------| | 1 | Fetch | | 2 | Fluffy | | 3 | Wag | | 1002 | Fetch | +---------+-----------+
Můžeme použít SELECT
příkaz s UNION
klauzule pro spojení výsledků z obou tabulek do jedné sady výsledků.
Příklad pomocí UNION ALL
Nejprve použijeme UNION ALL
tak, aby obsahoval duplikáty.
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Výsledek:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
V tomto případě se vrátí sedm řádků. Vidíme, že „Načíst“ je vráceno dvakrát. Je to proto, že existují dva psi jménem Fetch.
Je tu také kočka a pes se stejným jménem:Fluffy.
Všimněte si, že jsem k pojmenování pole vráceného operací použil alias sloupce. Pokud bych to neudělal, výsledek by použil názvy sloupců z prvního dotazu. V takovém případě by se záhlaví sloupce jmenovalo DogName
místo PetName
.
SELECT DogName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Výsledek:
+-----------+ | DogName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
To může nebo nemusí být přijatelné v závislosti na datech, která vracíte ve svém dotazu. V našem případě to není vhodné, protože ne všechny výsledky jsou psi.
Příklad pomocí UNION
Podívejme se, co se stane, když odstraníme ALL
argument.
SELECT DogName AS PetName
FROM Dogs
UNION
SELECT CatName
FROM Cats;
Výsledek:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Meow | | Scratch | | Wag | +-----------+ (5 rows affected)
Tentokrát je vráceno pouze pět řádků. Oba duplikáty jsou odstraněny.
UNION
vs DISTINCT
Všimněte si, že se to liší od použití DISTINCT
každému jednotlivému SELECT
prohlášení. Pokud bychom to udělali, Fluffy by byl vrácen dvakrát, protože ALL
platí pouze pro SELECT
prohlášení, proti kterému je aplikováno (nikoli na zřetězené výsledky).
Zde je příklad pro ilustraci toho, co mám na mysli.
SELECT DISTINCT DogName AS PetName
FROM Dogs
UNION ALL
SELECT DISTINCT CatName
FROM Cats;
Výsledek:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fluffy | | Meow | | Scratch | +-----------+ (6 rows affected)
Všechny dotazy musí vrátit stejný počet sloupců
Když použijete UNION
klauzule, každý dotaz musí mít stejný počet sloupců a musí být ve stejném pořadí.
Pokud ne, zobrazí se chyba.
SELECT CatName FROM Cats
UNION ALL
SELECT DogId, DogName FROM Dogs;
Výsledek:
Msg 205, Level 16, State 1, Line 1 All queries combined using a UNION, INTERSECT or EXCEPT operator must have an equal number of expressions in their target lists.
To je chyba, kterou SQL Server vrací při použití nestejného počtu sloupců. Tato konkrétní chyba znamená, že stejné omezení platí také pro INTERSECT
a EXCEPT
operátory. Chybová zpráva, kterou obdržíte, se může lišit v závislosti na vašem DBMS.
Typy dat musí být kompatibilní
Kromě požadavku na stejný počet sloupců musí mít tyto sloupce kompatibilní datový typ.
Nemusí nutně jít o stejný datový typ, ale musí být kompatibilní. To znamená, že musí být kompatibilní prostřednictvím implicitní konverze. Pokud se datové typy neshodují, musí být DBMS schopen provést implicitní konverzi, aby se shodovaly.
Pokud ne, zobrazí se chyba.
SELECT CatName FROM Cats
UNION ALL
SELECT DogId FROM Dogs;
Výsledek:
Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value 'Meow' to data type int.
Pořadí výsledků
Pokud chcete výsledky seřadit pomocí ORDER BY
klauzule, budete ji muset vložit do posledního dotazu. Nemůžete vložit samostatný ORDER BY
klauzule na každý dotaz, nebo v tomto případě jakýkoli dotaz, který není posledním.
Zde je chyba, kterou dostávám, když se to pokouším udělat na serveru SQL:
SELECT DogName AS PetName
FROM Dogs
ORDER BY DogName
UNION ALL
SELECT CatName
FROM Cats;
Výsledek:
Msg 156, Level 15, State 1, Line 4 Incorrect syntax near the keyword 'UNION'.
Pokud tedy chceme seřadit výsledky, budeme muset udělat něco takového:
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats
ORDER BY PetName;
Použití UNION
na Více než dva dotazy
Předchozí příklady zkombinovaly výsledky ze dvou různých dotazů, ale nic vám nebrání přidat další. V případě potřeby jej můžete použít ke spojení výsledků mnoha dotazů.
Pokud bychom například měli také Birds
stůl, mohli bychom udělat toto:
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats
UNION ALL
SELECT BirdName
FROM Birds;
Normalizace
Příklady na této stránce rozdělují kočky a psy do dvou samostatných tabulek. Důvod, proč jsem to udělal, je ten, že je to jasný a stručný způsob, jak ilustrovat, jak UNION
funguje.
V praxi je můžete mít ve stejné tabulce s názvem, řekněme Pets
, pak mít samostatný PetTypes
stůl (nebo podobný). Toto je známé jako normalizace a je to způsob, jakým jsou obvykle navrhovány relační databáze.
Poté můžete spustit spojení na těchto tabulkách a vrátit data podle potřeby.