Общи изрази за таблици или накратко CTE е просто техника за създаване на временен набор от записи, които могат да бъдат препратени в рамките на оператор INSERT, SELECT, UPDATE или DELETE.
Общи изрази за таблици бяха въведени от Microsoft в SQL Server 2005. Те не се съхраняват като обекти в паметта на базата данни, тъй като техният живот е равен на времето за изпълнение на заявката. Веднага след като заявката завърши, те се премахват от паметта на базата данни. CTE може да се препраща в заявка толкова пъти, колкото искате, и те също могат да се препращат самостоятелно.
Нека създадем база данни с таблица за студенти и да вмъкнем някои фиктивни студентски записи в нея. Ще използваме тази база данни за писане на CTE заявки. Както винаги, уверете се, че сте добре архивирани, преди да експериментирате с нов код. Вижте тази статия за архивиране на SQL, ако не сте сигурни.
Изпълнете следните заявки на вашия сървър.
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);
Сега, нека създадем много прост израз на обща таблица. Този CTE ще съдържа записи на всички ученици, родени преди 1 януари 1985 г. Разгледайте следния скрипт.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' )
За да създадете CTE, трябва да започнете с ключова дума „WITH“, последвана от името на CTE и ключовата дума „AS“.
След това, в скобите, трябва да напишете заявката, която връща записите, които CTE временно ще съхранява. В горния скрипт създадохме CTE с име „OldStudents“.
Имайте предвид обаче, че ако се опитате да изпълните горната заявка, ще получите грешка. Това е така, защото след като създадете CTE, трябва незабавно да го използвате.
Нека изберем всички записи от нашия новосъздадения CTE „OldStudents“. Опитайте следния скрипт на вашия сървър.
USE schooldb; WITH OldStudents AS ( SELECT * FROM student WHERE DOB < '1985-01-01' ) SELECT * FROM OldStudents
Горният скрипт ще извлече следния набор от записи:
Изчисляване на агрегат чрез CTE
Подобно на таблиците, можете да изпълнявате агрегатни функции на CTE. Нека да разгледаме друг пример за CTE.
USE schooldb; WITH SumofScores AS ( SELECT gender, SUM(total_score) as SumScore FROM student GROUP BY gender ) SELECT AVG (SumScore) FROM SumofScores
В горния пример създадохме CTE на име SumofScores. Този CTE съдържа сумата от стойностите, съхранени в колоната total_score на таблицата на учениците. Резултатът се групира по колоната за пол. Данните, съхранявани от CTE, изглеждат така в паметта:
След това изпълнихме функцията AVG в колоната „SumScore“ на CTE. Крайният резултат от скрипта ще бъде средната стойност от 2400 и 2730, т.е. 2565.
Това е малко по-сложно от предишния пример, но демонстрира концепцията за CTE по-ясно.
Етикетиране на колони в CTE
В предишния пример добавихме псевдоним към втората колона на CTE. Преименувахме го на „SumScore“. Това е един от начините за етикетиране на колони в CTE и е подобен на псевдонимите на колони в таблицата.
Има обаче друг начин за дефиниране на имена на колони в CTE. Разгледайте следната заявка.
USE schooldb; WITH SumofScores(Gender, SumScore) AS ( SELECT gender, SUM(total_score) FROM student GROUP BY gender ) SELECT AVG (SumScore) From SumofScores
В този скрипт добавихме имената на колоните на CTE „SumofScores“ в скоби след името на CTE. Името на всяка колона е разделено със запетая.
Ако погледнете израза SELECT след CTE, можете да видите, че тогава се позоваваме на колоната „SumScore“, която създадохме в скоби след името на CTE.
Създаване на множество CTEs
Всички примери досега са използвали само един общ израз на таблица за яснота. Можете да създадете списък с CTE едновременно и след това да използвате всички в комбинация в крайния набор от резултати.
Това се обяснява най-добре с помощта на пример. Разгледайте следния скрипт по-долу.
Тук ще създадем два CTE. Първият CTE ще съхранява всички записи на учениците, родени преди 1 януари 1985 г. Вторият CTE ще съдържа всички записи на студентите, родени на или след 1 януари 1985 г.
След това ще използваме оператори select, за да извлечем всички записи от двата CTE. Извлечените записи ще бъдат обединени заедно с помощта на оператор UNION. Накрая обединеният запис ще бъде сортиран във възходящ ред на датата на раждане.
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
В горната SQL заявка създадохме два CTE:„OldStudents“ и „YoungStudents“. Струва си да се спомене, че не е необходимо да използвате ключовата дума „WITH“ с всеки CTE. От вас се изисква да го използвате само преди първия CTE в скрипта, след което можете да създадете произволен брой CTE, като ги разделите със запетая.
Горният скрипт извлича следните резултати: