Vous êtes sur la page 1sur 16

WITH clause

A thorough guide through the concepts of SQL


COMMON TABLE EXPRESSION (CTE)
•A CTE is a virtual relation
•Similar to the ease of a temporary table
•Like a temporary named result set
•Commonly uses the WITH keyword in
SQL
WHY DO WE NEED TO USE CTE?
•Simplify your queries
•You can do recursion
•Better readability
CTE SYNTAX - WITH
• Queries start with WITH not SELECT
• Followed by the temporary name of the relation
• Then the attributes you want to extract
• Followed by the keyword AS
• Then the query enclosed in parentheses
• Then the queries using the temporary relation
Simple CTE Syntax
;WITH expression_name (column_name1, …)
AS OBSERVE THE REASON FOR
( ADDING A SEMICOLON
--Query Definition
)
SELECT column_name1, …
From expression_name;
What does WITH do?
Definition of said keyword
What is it?
• The SQL WITH clause allows you to give a sub-query
block a name (a process also called sub-query
refactoring), which can be referenced in several places
within the main SQL query.

IN OTHER WORDS, THIS IS A WAY TO GIVE A


SUB-QUERY A NAME FOR REUSABILITY AND
READABILITY
How does it work?
• The clause is used for defining a temporary relation such that the
output of this temporary relation is available and is used by the query
that is associated with the WITH clause

WITH temporaryTable (averageValue) as


(SELECT avg(Attr1)
FROM Table),
SELECT Attr1
FROM Table
WHERE Table.Attr1 >
temporaryTable.averageValue;
EMPLOYEE EMPLOYEEID NAME SALARY

100011 Smith 50000

Example 1: Find all the employees whose salary is more 100022 Bill 94000
than the average salary of all employees.
100027 Sam 70550
QUERY

WITH temporaryTable (averageValue) as 100845 Walden 80000


(SELECT avg(Attr1)
FROM Table), 115585 Erik 60000
SELECT Attr1
FROM Table 1100070 Kate 69000
WHERE Table.Attr1 > temporaryTable.averageValue;

OUTPUT:
EMPLOYEEID NAME SALARY

100022 Bill 94000

100845 Walden 80000


Take a look at these 2 queries
Query 1: Notice the 2 subqueries are Query 2: Notice that this is easier to
identically the same understand
• SELECT q1.department, q2.department AS • ;WITH deptCTE
subDepartment AS
FROM ( (
SELECT id, department, parent SELECT id, department, parent
FROM Departments FROM Departments
) AS q1 )
INNER JOIN SELECT q1.department,
( q2.department AS subDepartment
SELECT id, department, parent FROM FROM deptCTE as q1
Departments INNER JOIN deptCTE as q2
) as q2 ON q1.id = q2.parent
ON q1.id = q2.parent WHERE q1.parent IS NULL;
WHERE q1.parent IS NULL
MULTIPLE CTEs in a single query
• You can include multiple CTEs by comma separation:
;WITH firstCTE AS
(query goes here),
secondCTE AS
(second query goes here)
SELECT * FROM firstCTE
INNER JOIN secondCTE on…;
PILOT EMPLOYEEID AIRLINE NAME SALARY

70007 Airbus 380 Kim 60000


Example 2: Find all the airlines where the total salary of all
pilots in that airline is more than the average of total salary of 70002 Boeing Laura 20000
all pilots in the database.
QUERY 10027 Airbus 380 Will 80050
WITH totalSalary(Airline, total) as
(SELECT Airline, sum(Salary)
FROM Pilot 10778 Airbus 380 Warren 80780
GROUP BY Airline),
airlineAverage(avgSalary) as
115585 Boeing Smith 25000
(SELECT avg(Salary)
FROM Pilot )
SELECT Airline 114070 Airbus 380 Katy 78000
FROM totalSalary, airlineAverage
WHERE totalSalary.total > airlineAverage.avgSalary;

OUTPUT:
AIRLINE
Airbus 380
FirstNames Name
Rich
Example 3: Get all possible name combinations in the table of Drake
names.
QUERY
Danny
WITH Name Arnold
AS Raynold
(Select * from FirstNames)
n1.Name n2.Name
Name
SELECT n1.name, n2.name Rich
Rich Drake
FROM Name AS n1, Name AS n2
WHERE n1.name != n2.name; Drake
Drake Danny
Danny
Danny Arnold
Arnold
Arnold
Raynold Raynold
Raynold… Rich…
Simplifying
Complicated
Example 4: Based from an exam question, get the regions with
the highest high temperature and lowest low temperature. Queries
QUERY
WITH T1 (rID, high)
AS T5 (rID)
(SELECT rID, high
FROM Temp),
AS
(SELECT rID SELECT name
BASED FROM THIS RELATIONAL
T2 (rID, low)
AS
(SELECT rID, low
FROM (SELECT *
FROM Temp
except
FROM
(SELECT * SCHEMA
FROM (SELECT *
FROM Temp), SELECT * FROM TEMP
T3 (rID) FROM T3)), EXCEPT
AS T6 (rID) SELECT * FROM T5
(SELECT rID
FROM T1 NATURAL JOIN TEMP
AS
(SELECT rID
UNION
SELECT * FROM T6)
Temp(regionID, name, high, low)
WHERE T1.high<Temp.high), FROM (SELECT * );
T4 (rID) FROM Temp
AS except
(SELECT rID SELECT *
FROM T2 NATURAL JOIN TEMP FROM T4))
WHERE T2.low > Temp.low),
In milktea.sqlite, we can apply CTE in a
few of the queries we have done
before
I am sure we had trouble once with this certain
English Query…

EXAMPLE 5: Find all milk tea shops that are


visited by only females or only males (i.e.
visitors are all females or visitors are all
males).
Using CTE, we can be able to finally solve it
without just manually Union-ing the two
queries.

With just a bit of effort… 


FROM THIS WITH maleCostumer(milkteashop)
AS
(SELECT milkteashop
TROUBLESOME FROM Person NATURAL JOIN Visits
WHERE gender = 'male'),
QUERY femaleCostumer (milkteashop)
AS

TO THIS OTHER (SELECT milkteashop


FROM Person NATURAL JOIN Visits
WHERE gender = 'female'),
TROUBLESOME maleWithoutFemale (milkteashop)
SELECT milkteashop
FROM Person NATURAL JOIN
WHERE gender = 'female'
Visits YET WORKING AS
(SELECT milkteashop
FROM maleCostumer
EXCEPT
SELECT milkteashop
QUERY EXCEPT
SELECT milkteashop
FROM Person NATURAL JOIN Visits FROM femaleCostumer),
WHERE gender = 'male'
UNION Observation: femaleWithoutMale(milkteashop)
SELECT milkteashop AS
FROM Person NATURAL JOIN Visits Apparently applying (SELECT milkteashop
FROM femaleCostumer
WHERE gender = 'male' UNION to two EXCEPT
EXCEPT
SELECT milkteashop subqueries in set SELECT milkteashop
FROM maleCostumer)
FROM Person NATURAL JOIN Visits difference to another
WHERE gender = 'female' SELECT milkteashop
2 subqueries in set FROM maleWithoutFemale
difference to another UNION
SELECT milkteashop
has some particular FROM femaleWithoutMale;
problem to the
precedence
THANKS FOR
LISTENING!
Presentation by Jason Pascual
BSCS2B

Vous aimerez peut-être aussi