I SQL, UNION
sats sammanfogar resultaten av två frågor till en enda resultatuppsättning.
Du kan använda UNION
sats med eller utan ALL
argument:
UNION ALL
– Inkluderar dubbletter.UNION
– Exkluderar dubbletter.
Nedan följer några grundläggande exempel för att visa hur det fungerar.
Exempeltabeller
Anta att vi har två tabeller:Cats
och Dogs
Cats
+---------+-----------+ | CatId | CatName | |---------+-----------| | 1 | Meow | | 2 | Fluffy | | 3 | Scratch | +---------+-----------+
Dogs
+---------+-----------+ | DogId | DogName | |---------+-----------| | 1 | Fetch | | 2 | Fluffy | | 3 | Wag | | 1002 | Fetch | +---------+-----------+
Vi kan använda en SELECT
uttalande med en UNION
för att kombinera resultaten från båda tabellerna till en resultatuppsättning.
Exempel med UNION ALL
Låt oss först använda UNION ALL
så att den innehåller dubbletter.
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Resultat:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
I detta fall returneras sju rader. Vi kan se att "Hämta" returneras två gånger. Detta beror på att det finns två hundar som heter Fetch.
Det finns också en katt och en hund med samma namn:Fluffy.
Observera att jag använde ett kolumnalias för att namnge fältet som returneras av operationen. Om jag inte hade gjort det, skulle resultatet ha använt kolumnnamnen från den första frågan. I så fall skulle kolumnrubriken ha hetat DogName
istället för PetName
.
SELECT DogName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats;
Resultat:
+-----------+ | DogName | |-----------| | Fetch | | Fluffy | | Wag | | Fetch | | Meow | | Fluffy | | Scratch | +-----------+ (7 rows affected)
Detta kan vara acceptabelt eller inte, beroende på vilken data du returnerar i din fråga. I vårt fall är det inte lämpligt, eftersom inte alla resultat är hundar.
Exempel med UNION
Låt oss se vad som händer när vi tar bort ALL
argument.
SELECT DogName AS PetName
FROM Dogs
UNION
SELECT CatName
FROM Cats;
Resultat:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Meow | | Scratch | | Wag | +-----------+ (5 rows affected)
Denna gång returneras endast fem rader. Båda dubbletterna tas bort.
UNION
kontra DISTINCT
Observera att detta skiljer sig från att tillämpa DISTINCT
till varje enskild SELECT
påstående. Om vi hade gjort det skulle Fluffy ha returnerats två gånger, eftersom ALL
skulle endast gälla för SELECT
uttalande som det appliceras mot (inte på de sammanlänkade resultaten).
Här är ett exempel för att illustrera vad jag menar.
SELECT DISTINCT DogName AS PetName
FROM Dogs
UNION ALL
SELECT DISTINCT CatName
FROM Cats;
Resultat:
+-----------+ | PetName | |-----------| | Fetch | | Fluffy | | Wag | | Fluffy | | Meow | | Scratch | +-----------+ (6 rows affected)
Alla frågor måste returnera samma antal kolumner
När du använder UNION
klausul måste varje fråga ha samma antal kolumner och de måste vara i samma ordning.
Om inte, får du ett felmeddelande.
SELECT CatName FROM Cats
UNION ALL
SELECT DogId, DogName FROM Dogs;
Resultat:
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.
Det är felet som SQL Server returnerar när man använder ett ojämnt antal kolumner. Det här specifika felet indikerar att samma begränsning även gäller för INTERSECT
och EXCEPT
operatörer. Felmeddelandet du får kan vara annorlunda beroende på ditt DBMS.
Datatyper måste vara kompatibla
Förutom att kräva samma antal kolumner måste dessa kolumner ha en kompatibel datatyp.
De behöver inte nödvändigtvis vara av samma datatyp, men de måste vara kompatibla. Det vill säga att de måste vara kompatibla genom implicit konvertering. Om datatyperna inte matchar måste DBMS kunna göra en implicit konvertering så att de matchar.
Om inte, får du ett felmeddelande.
SELECT CatName FROM Cats
UNION ALL
SELECT DogId FROM Dogs;
Resultat:
Msg 245, Level 16, State 1, Line 1 Conversion failed when converting the varchar value 'Meow' to data type int.
Beställa resultaten
Om du vill sortera resultaten med ORDER BY
klausul måste du sätta den på den sista frågan. Du kan inte lägga en separat ORDER BY
klausul på varje fråga, eller för den delen, vilken fråga som helst som inte är den sista.
Här är felet jag får när jag försöker göra det i SQL Server:
SELECT DogName AS PetName
FROM Dogs
ORDER BY DogName
UNION ALL
SELECT CatName
FROM Cats;
Resultat:
Msg 156, Level 15, State 1, Line 4 Incorrect syntax near the keyword 'UNION'.
Därför, om vi vill beställa resultaten, måste vi göra något så här:
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats
ORDER BY PetName;
Använder UNION
till Mer än två frågor
De tidigare exemplen kombinerade resultat från två olika frågor, men det finns inget som hindrar dig från att lägga till fler. Du kan använda den för att kombinera resultaten av många frågor om det behövs.
Till exempel, om vi också hade en Birds
tabell kan vi göra detta:
SELECT DogName AS PetName
FROM Dogs
UNION ALL
SELECT CatName
FROM Cats
UNION ALL
SELECT BirdName
FROM Birds;
Normalisering
Exemplen på den här sidan placerar katter och hundar i två separata tabeller. Anledningen till att jag gjorde detta är att det är ett tydligt och kortfattat sätt att illustrera hur UNION
fungerar.
I praktiken kanske du har dessa i samma tabell som heter, säg Pets
, har sedan en separat PetTypes
bord (eller liknande). Detta är känt som normalisering, och är hur relationsdatabaser vanligtvis är utformade.
Du kan sedan köra en join på dessa tabeller för att returnera data efter behov.