Common Table Expressions, nebo zkráceně CTE, je jednoduše technika k vytvoření dočasné sady záznamů, na které lze odkazovat v příkazech INSERT, SELECT, UPDATE nebo DELETE.
Společné tabulkové výrazy byly zavedeny společností Microsoft v SQL Server 2005. Nejsou uloženy jako objekty v paměti databáze, protože jejich životnost se rovná době provedení dotazu. Jakmile je dotaz dokončen, jsou odstraněny z paměti databáze. CTE lze v dotazu odkazovat tolikrát, kolikrát chcete, a mohou se také odkazovat na sebe.
Vytvořme databázi s tabulkou studentů a vložíme do ní nějaké fiktivní záznamy studentů. Tuto databázi použijeme pro psaní CTE dotazů. Jako vždy se ujistěte, že jste před experimentováním s novým kódem dobře zálohováni. Pokud si nejste jisti, přečtěte si tento článek o zálohování SQL.
Proveďte na svém serveru následující dotazy.
CREATE DATABASE schooldb CREATE TABLE student ( id INT PRIMARY KEY, name VARCHAR(50) NOT NULL, gender VARCHAR(50) NOT NULL, DOB datetime NOT NULL, total_score INT NOT NULL, ) INSERT INTO student VALUES (1, 'Jolly', 'Female', '12-JUN-1989', 500), (2, 'Jon', 'Male', '02-FEB-1974', 545), (3, 'Sara', 'Female', '07-MAR-1988', 600), (4, 'Laura', 'Female', '22-DEC-1981', 400), (5, 'Alan', 'Male', '29-JUL-1993', 500), (6, 'Kate', 'Female', '03-JAN-1985', 500), (7, 'Joseph', 'Male', '09-APR-1982', 643), (8, 'Mice', 'Male', '16-AUG-1974', 543), (9, 'Wise', 'Male', '11-NOV-1987', 499), (10, 'Elis', 'Female', '28-OCT-1990', 400);
Nyní vytvoříme velmi jednoduchý společný tabulkový výraz. Tento CTE bude obsahovat záznamy všech studentů, kteří se narodili před 1. lednem 1985. Podívejte se na následující skript.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' )
Chcete-li vytvořit CTE, musíte začít klíčovým slovem „WITH“ následovaným názvem klíčového slova CTE a „AS“.
Dále v závorce musíte napsat dotaz, který vrátí záznamy, které CTE dočasně uloží. Ve výše uvedeném skriptu jsme vytvořili CTE s názvem „OldStudents“.
Pamatujte však, že pokud se pokusíte provést výše uvedený dotaz, zobrazí se chyba. Je to proto, že jakmile vytvoříte CTE, musíte jej okamžitě použít.
Vyberme všechny záznamy z našeho nově vytvořeného CTE „OldStudents“. Vyzkoušejte na svém serveru následující skript.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' ) SELECT * FROM OldStudents
Výše uvedený skript načte následující sadu záznamů:
Výpočet agregace pomocí CTE
Stejně jako tabulky můžete na CTE provádět agregační funkce. Podívejme se na další příklad CTE.
USE schooldb; WITH SumofScores AS ( SELECT gender, SUM(total_score) as SumScore FROM student GROUP BY gender ) SELECT AVG (SumScore) FROM SumofScores
Ve výše uvedeném příkladu jsme vytvořili CTE s názvem SumofScores. Tento CTE obsahuje součet hodnot uložených ve sloupci total_score tabulky studentů. Výsledek je seskupen podle sloupce pohlaví. Data uložená v CTE vypadají v paměti takto:
Dále jsme provedli funkci AVG ve sloupci „SumScore“ CTE. Konečným výsledkem skriptu bude průměr 2400 a 2730, tj. 2565.
Toto je o něco složitější než předchozí příklad, ale názorněji demonstruje koncept CTE.
Označení sloupců v CTE
V předchozím příkladu jsme přidali alias do druhého sloupce CTE. Přejmenovali jsme to na „SumScore“. Toto je jeden způsob označování sloupců v CTE a je podobný aliasům sloupců tabulky.
Existuje však jiný způsob, jak definovat názvy sloupců v CTE. Podívejte se na následující dotaz.
USE schooldb; WITH SumofScores(Gender, SumScore) AS ( SELECT gender, SUM(total_score) FROM student GROUP BY gender ) SELECT AVG (SumScore) From SumofScores
V tomto skriptu jsme přidali názvy sloupců CTE „SumofScores“ do závorek za název CTE. Každý název sloupce je oddělen čárkou.
Pokud se podíváte na příkaz SELECT za CTE, můžete vidět, že pak odkazujeme na sloupec „SumScore“, který jsme vytvořili v závorce za názvem CTE.
Vytvoření více CTE
Všechny dosavadní příklady pro přehlednost používaly pouze jeden společný tabulkový výraz. Můžete vytvořit seznam CTE současně a poté je všechny použít v kombinaci v konečné sadě výsledků.
Nejlépe je to vysvětleno na příkladu. Podívejte se na následující skript níže.
Zde vytvoříme dva CTE. První CTE bude ukládat všechny záznamy studentů narozených před 1. lednem 1985. Druhý CTE bude obsahovat všechny záznamy studentů narozených 1. ledna 1985 nebo později.
Poté použijeme příkazy select k načtení všech záznamů z obou CTE. Načtené záznamy budou sloučeny dohromady pomocí příkazu UNION. Nakonec bude sloučený záznam seřazen vzestupně podle data narození.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' ), YoungStudents AS ( SELECT * FROM student WHERE DOB >= '1985-01-01' ) (SELECT * FROM OldStudents UNION SELECT * FROM YoungStudents) ORDER BY DOB
Ve výše uvedeném SQL dotazu jsme vytvořili dva CTE:„OldStudents“ a „YoungStudents“. Stojí za zmínku, že nemusíte používat klíčové slovo „WITH“ u každého CTE. Musíte jej použít pouze před prvním CTE ve skriptu, poté můžete vytvořit libovolný počet CTE tak, že je oddělíte čárkou.
Výše uvedený skript načte následující výsledky: