Subquery returnerar en tabell
Och slutligen, det tredje alternativet är när underfrågan returnerar hela tabellen. Detta är det vanligaste alternativet.
Mycket ofta finns det situationer när vi vill justera ett visst bord lite. Och först därefter sammanfoga (med JOIN ON-operatorn) den korrigerade tabellen med en annan.
Låt oss börja med det enklaste fallet, där vi sammanfogade två tabeller med en JOIN:
SELECT * FROM employee e JOIN task t ON e.id = t.emploee_id
Och som du säkert kommer ihåg finns det uppgifter i uppgiftstabellen som inte är tilldelade någon: anställd_id är NULL .
Låt oss skapa en korrigerad tabell , där vi tilldelar alla hängande uppgifter till regissören (hans ID = 4).
För att göra detta använder vi funktionen IFNULL() :
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline FROM task
Och resultatet av denna fråga:
id | Anställnings-ID | namn | deadline |
---|---|---|---|
1 | 1 | Fixa en bugg på frontend | 2022-06-01 |
2 | 2 | Fixa en bugg på backend | 2022-06-15 |
3 | 5 | Köp kaffe | 2022-07-01 |
4 | 5 | Köp kaffe | 2022-08-01 |
5 | 5 | Köp kaffe | 2022-09-01 |
6 | 4 | Städa kontoret | (NULL) |
7 | 4 | Njut av livet | (NULL) |
8 | 6 | Njut av livet | (NULL) |
Den korrigerade cellen är markerad med rött.
Låt oss nu ersätta vår korrigerade tabell i frågan:
SELECT * FROM employee e JOIN task t ON e.id = t.emploee_id
Istället för uppgiftstabellen .
En sådan begäran skulle se ut ungefär så här:
SELECT * FROM employee e JOIN (
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline
FROM task
) t ON e.id = t.emploee_id
Istället för ordet uppgift skrev vi parenteser och placerade förfrågningskroppen i dem.
Förresten, aliaset t (alias) för den kapslade frågan var mycket användbart. En kapslad fråga, till skillnad från en tabell, har inte ett eget namn, så aliaset är väldigt malplacerat.
Och här är resultatet av en sådan fråga:
id | namn | ockupation | lön | ålder | join_date | id | Anställnings-ID | namn |
---|---|---|---|---|---|---|---|---|
1 | Ivanov Ivan | Programmerare | 100 000 | 25 | 2012-06-30 | 1 | 1 | Fixa en bugg på frontend |
2 | Petrov Petr | Programmerare | 80 000 | 23 | 2013-08-12 | 2 | 2 | Fixa en bugg på backend |
4 | Rabinovich Moisha | Direktör | 200 000 | 35 | 2015-05-12 | 6 | 4 | Städa kontoret |
4 | Rabinovich Moisha | Direktör | 200 000 | 35 | 2015-05-12 | 7 | 4 | Njut av livet |
5 | Kirienko Anastasia | Kontors chef | 40 000 | 25 | 2015-10-10 | 4 | 5 | Köp kaffe |
5 | Kirienko Anastasia | Kontors chef | 40 000 | 25 | 2015-10-10 | 5 | 5 | Köp kaffe |
5 | Kirienko Anastasia | Kontors chef | 40 000 | 25 | 2015-10-10 | 3 | 5 | Köp kaffe |
6 | Vaska | katt | 1000 | 3 | 2018-11-11 | 8 | 6 | Njut av livet |
Vår direktör har till uppgift att "städa upp på kontoret", jag tror att han snabbt hittar någon att delegera det till :) Använder WITH-operatören
Förresten, från och med version 8 av MySQL behöver du inte längre lägga alla dina underfrågor direkt i den slutliga frågan. De kan utföras separat. För detta används WITH-satsen .
Det låter dig skapa en virtuell tabell (med namnet fråga) och dess utseende ges av en mall:
WITH Name AS (request)
Det finns ofta tillfällen när din underfråga har namnlösa kolumner, som COUNT(*), som du inte har tilldelat ett unikt namn. I det här fallet har WITH-satsen möjlighet att ange nya kolumnnamn för underfrågan.
Dess andra form ges av mallen:
WITH Name(column1, column2, …) AS (request)
Du kan använda så många virtuella tabeller (namngivna frågor) som du vill och hänvisa till varandra i dem. Den allmänna formen för din begäran kommer att ha något så här:
WITH name1 AS (request1),
name2 AS (request2),
name3 AS (request3)
SELECT * FROM name1 JOIN name2 ON …
Låt oss nu ta vår skrämmande fråga:
SELECT * FROM employee e JOIN (
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline
FROM task
) t ON e.id = t.emploee_id
Och skriv om det med hjälp av WITH-satsen:
WITH task2(id, employee_id, name, deadline)
AS (SELECT id, IFNULL(employee_id, 4), name, deadline FROM task)
SELECT * FROM employee e JOIN task2 t ON e.id = t.emploee_id
Eller så kan du göra utan kolumnnamn, men då måste du ange ett alias för IFNULL()-funktionen:
WITH task2 AS (
SELECT id, IFNULL(employee_id, 4) AS employee_id, name, deadline FROM task
)
SELECT * FROM employee e JOIN task2 t ON e.id = t.emploee_id
GO TO FULL VERSION