sql >> Database teknologi >  >> RDS >> Mysql

MySQL 8 Almindelige tabeludtryk CTE

MySQL 8 understøtter almindelige tabeludtryk, både ikke-rekursive og rekursive. En CTE (Common Table Expression) er et midlertidigt resultatsæt, som du kan referere til i en anden SELECT-, INSERT-, UPDATE- eller DELETE-sætning.

Ikke-rekursiv CTE

Et almindeligt tabeludtryk (CTE) er ligesom en afledt tabel, men dens erklæring sættes før forespørgselsblokken i stedet for i FROM-klausulen. Ved at bruge CTE evalueres underforespørgslen kun én gang, Fælles tabeludtryk muliggør brugen af ​​navngivne midlertidige resultatsæt, Fælles tabeludtryk defineres i sætningen ved hjælp af WITH-operatoren.

Antag, at du vil finde ud af den procentvise ændring i betalingerne for hvert år i forhold til det foregående år. Uden CTE skal du skrive to underforespørgsler, og de er i det væsentlige ens. MySQL er ikke smart nok til at opdage det, og underforespørgslerne udføres to gange.

VÆLG q1.years,q2.years AS next_year,q1.sum1,q2.sum1 AS next_sum,100 * (q2.sum1 - q1.sum1) / q1.sum1 AS pctFROM(SELECT YEAR(paymentDate) AS years, SUM(beløb) AS sum1 FRA betalinger GRUPPER EFTER år) AS q1,(SELECT YEAR(paymentDate) AS years, SUM(beløb) AS sum1 FRA betalinger GRUPPER EFTER år) AS q2WHEREq1.years =q2.years - 1;+-- -----+-----------+-------------+-------------- ------+| år | næste_år | sum1 | næste_sum | pct |+-------+-----------------------+- -----------+| 2003 | 2004 | 3250217,70 | 4313328,25 | 32.708903 || 2004 | 2005 | 4313328,25 | 1290293,28 | -70.085901 |+-------+------------+------------+------------+ ------------+2 rækker i sæt (0,01 sek.)

Med ikke-rekursiv CTE udføres den afledte forespørgsel kun én gang og genbruges

WITH CTE_NAME AS (SELECT YEAR(paymentDate) AS years, SUM(amount) AS sum1 FROM payments GROUP BY years)SELECT q1.years,q2.years AS next_year,q1.sum1,q2.sum1 AS next_sum,100 * (q2.sum1 - q1.sum1) / q1.sum1 AS pct FRA CTE_NAME AS q1,CTE_NAME AS q2 HVOR q1.years =q2.years - 1;+-------+------- ----+------------+------------+------------+| år | næste_år | sum1 | næste_sum | pct |+-------+-----------------------+- -----------+| 2003 | 2004 | 3250217,70 | 4313328,25 | 32.708903 || 2004 | 2005 | 4313328,25 | 1290293,28 | -70.085901 |+-------+------------+------------+------------+ ------------+2 rækker i sæt (0,00 sek.)

Du bemærker måske, at med CTE er resultaterne de samme, og forespørgselstiden forbedres med 50 %, læsbarheden er god og kan refereres flere gange

CTE'er kan henvise til andre CTE'er:WITH cte1 AS (SELECT ... FROM ...), cte2 AS (SELECTFROM cte1 ...)SELECTFROM cte1, cte2 ...

Rekursive CTE'er

En rekursiv CTE er en CTE, der refererer til sig selv. Ved at gøre dette udføres den indledende CTE gentagne gange, hvilket returnerer delmængder af data, indtil det komplette resultat returneres

MED RECURSIVE cte_name AS(cte_definition -- /* seed SELECT */UNION ALLcte_definition -- /* "recursive" SELECT */ referencer cte_name.)-- Udsagn ved hjælp af CTESELECT *FROM cte_name

Seed SELECT udføres én gang for at skabe det indledende dataundersæt; rekursiv SELECT udføres gentagne gange for at returnere delmængder af data, indtil det komplette resultatsæt er opnået. Rekursionen stopper, når en iteration ikke genererer nye rækker.

Antag, at du vil lave hierarkisk datagennemgang for at producere et organisationsdiagram med ledelseskæden for hver medarbejder (det vil sige vejen fra CEO til en medarbejder). Brug en rekursiv CTE! Rekursive CTE'er er velegnede til at forespørge hierarkiske data,

Opret tabel

CREATE TABLE mangeremp (id INT PRIMARY KEY NOT NULL,name VARCHAR(100) NOT NULL,man_id INT NULL,INDEX (man_id),FOREIGN KEY (man_id) REFERENCES mangeremp (id));

indsæt data for at få hierarkisk struktur

INSERT INTO mangeremp VALUES(333, "waqas", NULL), # waqas er CEO (man_id er NULL)(198, "ali", 333), # ali har ID 198 og rapporterer til 333 (waqas)( 692, "ahmed", 333), #ahmed rapport til waqas(29, "oasama", 198), #osama rapport til ali as alo har ref id 198(4610, "Mughees", 29), # Mughees rapport til osama (72, "aslam", 29),(123, "afrooz", 692);
MED REKURSIVE emp_paths (id, navn, sti) AS (SELECT id, name, CAST(id AS CHAR(200)) FRA mangeremp WHERE man_id IS NULL UNION ALLE VÆLG e.id, e.name, CONCAT(ep. sti, ',', e.id) FRA emp_paths AS ep JOIN mangeremp AS e ON ep.id =e.man_id )SELECT * FROM emp_paths BESTIL EFTER sti;+------+------- --+-----------------+| id | navn | sti |+------+---------+----------------+| 333 | waqas | 333 || 198 | ali | 333.198 || 29 | oasama | 333.198,29 || 4610 | Mughees | 333,198,29,4610 || 72 | aslam | 333,198,29,72 || 692 | ahmed | 333.692 || 123 | afrooz | 333.692.123 |+------+--------+----------------+7 rækker i sæt (0,00 sek.)
VÆLG e.id, e.name, CONCAT(ep.path, ',', e.id) FROM emp_paths AS ep JOIN mangeremp AS e ON ep.id =e.man_id ---- rekursiv forespørgsel 

Hver række produceret af den rekursive forespørgsel finder alle medarbejdere, der rapporterer direkte til en
medarbejder produceret af en tidligere række. For hver sådan medarbejder inkluderer rækken
medarbejder-id, navn og medarbejderledelseskæde. Kæden er lederens kæde
med medarbejder-id tilføjet til sidst


  1. Tanker om SQL Server 2019-udgaver

  2. Returner rækker fra INSERT med ON CONFLICT uden at skulle opdatere

  3. Postgres heltalsarrays som parametre?

  4. Indstil standardværdien for en heltalskolonne SQLite