Kapslade frågor i SQL
SQL-språket låter dig kapsla en fråga i en annan fråga. Detta gör det möjligt att skriva en mycket stor fråga som kommer att göra något stort och komplext, även om kodens läsbarhet är avsevärt reducerad.
Beroende på hur många värden som returneras av underfrågor ändras området där de kan tillämpas. Det finns tre alternativ totalt:
- Underfrågan returnerar ett enda värde (en kolumn och en rad).
- Underfrågan returnerar en lista med värden (en tabell med en kolumn).
- Underfrågan returnerar en tabell (många kolumner, valfritt antal rader).
Låt oss titta på ett exempel för varje fall.
Underfråga med skalärt resultat
Låt oss hitta en lista över alla våra anställda från personaltabellen vars lön är högre än genomsnittet för företaget. Hur kan vi göra det?
Vi kan enkelt filtrera anställda genom att jämföra deras lön med genomsnittet om vi vet det i förväg. Samtidigt har vi redan skrivit en fråga som gör att vi kan beräkna snittlönen för företagets anställda. Låt oss komma ihåg det:
SELECT AVG(salary) FROM employee
Sedan returnerade MySQL oss värdet: 76833.3333 .
Hur hittar man nu en lista över alla anställda vars lön är över genomsnittet? Det är också väldigt enkelt:
SELECT * FROM employee
WHERE salary > 76833.3333
Resultatet av denna fråga blir:
id | namn | ockupation | lön |
---|---|---|---|
1 | Ivanov Ivan | Programmerare | 100 000 |
2 | Petrov Petr | Programmerare | 80 000 |
4 | Rabinovich Moisha | Direktör | 200 000 |
Och nu kombinerar vi bara båda begäranden genom att ersätta den första begäran istället för värdet 76833:
SELECT * FROM employee
WHERE salary > (SELECT AVG(salary) FROM employee)
Resultatet av denna fråga blir detsamma:
id | namn | ockupation | lön |
---|---|---|---|
1 | Ivanov Ivan | Programmerare | 100 000 |
2 | Petrov Petr | Programmerare | 80 000 |
4 | Rabinovich Moisha | Direktör | 200 000 |
Underfråga med värdelista
Kommer du ihåg att vi en gång i tiden hade en uppgift - att hitta alla poster från en tabell som det inte finns motsvarande poster för från en annan?
Det fanns även denna bild:
Om jag inte har fel så är uppgiften följande: visa en lista över alla anställda från personaltabellen för vilka det inte finns några uppgifter i uppgiftstabellen .
Låt oss också hitta en lösning i två steg.
Låt oss först skriva en fråga som returnerar id:t för alla anställda som har uppgifter i uppgiftstabellen. Kom bara ihåg två saker:
- ta bort dubbletter - använd nyckelordet DISTINCT.
- ta bort NULL-värden från resultatet.
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
Och här fick vi ett vackert resultat av en sådan begäran:
Anställnings-ID |
---|
1 |
2 |
5 |
4 |
6 |
Låt oss tillfälligt skriva ner det för bekvämlighets skull som en sekvens: 1,2,5,4,6. Låt oss nu skriva en andra fråga - till medarbetartabellen, som kommer att returnera en lista över anställda vars ID inte finns i den första listan:
SELECT * FROM employee
WHERE id NOT IN (1,2,5,4,6)
Och resultatet av denna fråga:
id | namn | ockupation | lön | ålder | join_date |
---|---|---|---|---|---|
3 | Ivanov Sergey | Testare | 40 000 | trettio | 2014-01-01 |
Och nu, som i det föregående exemplet, kan du kombinera båda förfrågningarna genom att helt enkelt ersätta brödtexten i den första förfrågan istället för id-listan.
SELECT * FROM employee
WHERE id NOT IN (
SELECT DISTINCT employee_id FROM task
WHERE employee_id IS NOT NULL
)
GO TO FULL VERSION