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