sql >> Databáze >  >> RDS >> Mysql

MySQL 8 běžné tabulkové výrazy CTE

MySQL 8 podporuje běžné tabulkové výrazy, nerekurzivní i rekurzivní. CTE (Common Table Expression) je dočasná sada výsledků, na kterou můžete odkazovat v rámci jiného příkazu SELECT, INSERT, UPDATE nebo DELETE.

Nerekurzivní CTE

Běžný tabulkový výraz (CTE) je stejný jako odvozená tabulka, ale jeho deklarace je umístěna před blok dotazu místo v klauzuli FROM. Pomocí CTE je poddotaz vyhodnocen pouze jednou, Společné tabulkové výrazy umožňují použití pojmenovaných dočasných výsledkových sad, Společné tabulkové výrazy jsou definovány v rámci příkazu pomocí operátoru WITH.

Předpokládejme, že chcete zjistit procentuální změnu plateb každého roku vzhledem k předchozímu roku. Bez CTE musíte napsat dva poddotazy a jsou v podstatě stejné. MySQL není dostatečně chytré, aby to zjistilo, a poddotazy se provádějí dvakrát.

SELECT 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, SOUČET(částka) JAKO součet1 Z plateb SKUPINY DLE let) JAKO q1,(VYBRAT ROK(Datum platby) JAKO roky, SOUČET(částka) JAKO součet1 Z plateb SKUPINY DLE let) JAKO q2WHEREq1.roky =q2.roky - 1;+-- -----+-----------+------------+------------+------ ------+| let | příští_rok | součet1 | další_součet | pct |+-------+-----------+------------+------------+- -----------+| 2003 | 2004 | 3250217,70 | 4313328,25 | 32,708903 || 2004 | 2005 | 4313328,25 | 1290293,28 | -70,085901 |+-------+-----------+------------+------------+ ------------+2 řádky v sadě (0,01 s)

U nerekurzivního CTE je odvozený dotaz proveden pouze jednou a znovu použit

S CTE_NAME AS (SELECT YEAR(datum platby) AS roky, SUM(částka) AS součet1 Z plateb GROUP BY roků)SELECT q1.years,q2.years AS next_year,q1.sum1,q2.sum1 AS next_sum,100 * (q2.sum1 - q1.sum1) / q1.sum1 AS pct FROM CTE_NAME AS q1,CTE_NAME AS q2 WHERE q1.years =q2.years - 1;+-------+-------- ----+------------+------------+------------+| let | příští_rok | součet1 | další_součet | pct |+-------+-----------+------------+------------+- -----------+| 2003 | 2004 | 3250217,70 | 4313328,25 | 32,708903 || 2004 | 2005 | 4313328,25 | 1290293,28 | -70,085901 |+-------+-----------+------------+------------+ ------------+2 řádky v sadě (0,00 s)

Můžete si všimnout, že s CTE jsou výsledky stejné a doba dotazování se zlepšila o 50 %, čitelnost je dobrá a lze na ni odkazovat vícekrát

CTE mohou odkazovat na jiné CTE:WITH cte1 AS (SELECT ... FROM ...), cte2 AS (SELECT ... FROM cte1 ...)SELECTFROM cte1, cte2 ...

Rekurzivní CTE

Rekurzivní CTE je CTE, která odkazuje sama na sebe. Přitom se opakovaně provádí počáteční CTE a vrací podmnožiny dat, dokud se nevrátí úplný výsledek

S REKURSIVNÍM cte_name AS(cte_name AS(cte_definition -- /* seed SELECT */UNION ALLcte_definition -- /* "rekurzivní" SELECT */ odkazy cte_name.)-- Příkaz používající CTESELECT *FROM cte_name

Seed SELECT se provede jednou pro vytvoření počáteční datové podmnožiny; rekurzivní SELECT se opakovaně provádí, aby se vrátily podmnožiny dat, dokud není získána úplná sada výsledků. Rekurze se zastaví, když iterace nevygeneruje žádné nové řádky.

Předpokládejme, že chcete provést hierarchické procházení dat, abyste vytvořili organizační schéma s řídicím řetězcem pro každého zaměstnance (tj. cestu od generálního ředitele k zaměstnanci). Použijte rekurzivní CTE! Rekurzivní CTE se dobře hodí k dotazování na hierarchická data,

Vytvořit tabulku

CREATE TABLE mangeremp (id INT PRIMARY KEY NOT NULL,name VARCHAR(100) NOT NULL,man_id INT NULL,INDEX (man_id),CIZI KLÍČ (man_id) REFERENCE mangeremp (id));

vložte data, abyste získali hierarchickou strukturu

INSERT INTO mangeremp VALUES(333, "waqas", NULL), # waqas je CEO (man_id je NULL)(198, "ali", 333), # ali má ID 198 a hlásí se na 333 (waqas)( 692, "ahmed", 333), #ahmed nahlásit waqas(29, "oasama", 198), #osama nahlásit ali as alo má ref id 198(4610, "Mughees", 29), # Mughees nahlásit usmovi (72, "aslam", 29),(123, "afrooz", 692);
S REKURSIVNÍM emp_paths (id, jméno, cesta) AS (SELECT id, jméno, CAST(id AS CHAR(200)) FROM mangeremp WHERE man_id JE NULL UNION ALL SELECT e.id, e.name, CONCAT(ep. cesta, ',', e.id) FROM emp_paths AS ep PŘIPOJIT SE mangeremp AS e ON ep.id =e.man_id )SELECT * Z emp_paths ORDER BY path;+------+-------- --+------------------+| id | jméno | cesta |+------+---------+-----------------+| 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 řádků v sadě (0,00 s)
SELECT e.id, e.name, CONCAT(ep.path, ',', e.id) FROM emp_paths AS ep JOIN mangeremp AS e ON ep.id =e.man_id ---- rekurzivní dotaz 

Každý řádek vytvořený rekurzivním dotazem najde všechny zaměstnance, kteří se hlásí přímo
zaměstnanci vytvořenému předchozím řádkem. Pro každého takového zaměstnance řádek obsahuje
ID zaměstnance, jméno a řetězec vedení zaměstnanců. Řetězec je řetězec manažera
s ID zaměstnance přidaným na konci


  1. Tipy pro ukládání záloh PostgreSQL na Amazon AWS

  2. Jak vytvářet a udržovat databáze MySQL v cPanel

  3. PostgreSQL vrátí výsledek jako pole JSON?

  4. Psychopg2 využívá paměť na velký výběrový dotaz