sql >> Databasteknik >  >> RDS >> Database

SQL UNION-klausul för nybörjare

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.


  1. Är det en dålig idé att ha ett "ELLER" i ett INNER JOIN-tillstånd?

  2. Trimma mer transaktionsloggfett

  3. SCD typ 1

  4. Förstå Dirty Read-problem med SQL Server