Académique Documents
Professionnel Documents
Culture Documents
Windows 3.1?
So why stick to
SQL-92?
SQL:1999
LATERAL
o
t
e
u
d
L
d
A
i
l
R
a
E
V
T
d
A
r
L
o
w
y
e
k
SELECT
*
FROM
t1
JOIN
LATERAL
(SELECT
*
FROM
t2
WHERE
t2.x
=
t1.x
)
inline_view
ON
(true)
o
t
e
u
d
L
d
A
i
l
R
a
E
V
T
d
A
r
L
o
w
y
e
k
SELECT
*
FROM
t1
JOIN
LATERAL
(SELECT
*
t
FROM
t2
u
b
,
s
d
e
s
WHERE
t2.x
=
t1.x
r
e
i
l
e
u
q
s
e
U
)
inline_view
r
l
l
i
t
s
ON
(true)
But WHY?
Join
everything
Join
everything
Join
everything
Join
everything
Join
everything
times # of
subscriptions
times # of
subscriptions
LATERAL in an Nutshell
LATERAL is the "for each" loop of SQL
LATERAL plays well with outer joins
LATERAL is an optimization Super-Power
LATERAL handy to join table functions
WITH
(Common Table Expressions)
e
s
n
e
s
s
e
k
a
m
e
in
l
t
s
Finally the fir
SELECT
FROM
(SELECT
FROM
t1
JOIN
(SELECT
FROM
)
a
ON
()
)
b
JOIN
(SELECT
FROM
)
c
ON
()
Key wor d
WITH
a
(c1,
c2,
c3)
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
N am e o f C TE a nd (he re
o p ti on a l ) c olu mn n a me s
WITH
a
(c1,
c2,
c3)
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
Don't repeat
WITH
WITH
a
(c1,
c2,
c3)
WITH
Since SQL:99
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
c
()
AS
(SELECT
FROM
)
SELECT
FROM
b
JOIN
c
ON
()
WITH
a
(c1,
c2,
c3)
WITH
Since SQL:99
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
T h ird CTE
c
()
AS
(SELECT
FROM
)
SELECT
FROM
b
JOIN
c
ON
()
WITH
a
(c1,
c2,
c3)
WITH
Since SQL:99
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
c
()
AS
(SELECT
FROM
)
SELECT
FROM
b
JOIN
c
ON
()
N o co mma !
WITH
a
(c1,
c2,
c3)
WITH
Since SQL:99
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
c
()
AS
(SELECT
FROM
)
SELECT
FROM
b
JOIN
c
ON
()
Ma in q ue ry
WITH
Since
SQL:99
CTEs are statement-scoped views:
WITH
a
(c1,
c2,
c3)
AS
(SELECT
c1,
c2,
c3
FROM
),
b
(c4,
)
AS
(SELECT
c4,
FROM
t1
JOIN
a
ON
()
),
c
()
AS
(SELECT
FROM
)
SELECT
FROM
b
JOIN
c
ON
()
d
a
n
e
w
R
o
d
p
o
t
WITH in an Nutshell
WITH are the "private methods" of SQL
WITH views can be referred to multiple times
WITH allows chaining instead of nesting
WITH is allowed where SELECT is allowed
INSERT
INTO
tbl
WITH
...
SELECT
...
WITH
cte
AS
(SELECT
*
FROM
news)
SELECT
*
FROM
cte
WHERE
topic=1
$%
$%
$%
'
()
"
"*
&
+#'
,
!""-'"
.#
/01/2.0..30
'
,
" 45&
!""-'"!
$%
!"#
&
"
WITH
RECURSIVE
(Common Table Expressions)
Key wor d
t
s
i
l
n
Colum ry here
WITH
RECURSIVE
cte
(n) m a n d a t o
AS
(SELECT
1
UNION
ALL
SELECT
n+1
FROM
cte
WHERE
n
<
3)
SELECT
*
FROM
cte;
Result
WITH
RECURSIVE
cte
(n) sent there
AS
(SELECT
1
UNION
ALL
SELECT
n+1
FROM
cte
WHERE
n
<
3)
SELECT
*
FROM
cte;
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
Result
WITH
RECURSIVE
cte
(n) sent there
again
AS
(SELECT
1
UNION
ALL
SELECT
n+1
FROM
cte
WHERE
n
<
3)
SELECT
*
FROM
cte;
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
n
---
1
2
3
(3
rows)
'$(
)(#$
*+
,"-
+..+
,($
&-&$
",
&$$&"/#
/
0(#1
$1&#
(0
$"
+
/
,"
$"0.%
#$$-/$#
!"#$
%
&$
SQL:2003
FILTER
FROM
sale_data
GROUP
BY
YEAR;
" "
!
#
OVER
and
PARTITION BY
WITH
total_salary_by_department
AS
(SELECT
dep,
SUM(salary)
total
FROM
emp
GROUP
BY
dep)
SELECT
dep,
emp_id,
salary,
salary/ts.total*100
"%
of
dep"
FROM
emp
JOIN
total_salary_by_department
ts
ON
(emp.dep
=
ts.dep)
WHERE
emp.dep
=
?
WITH
total_salary_by_department
AS
(SELECT
dep,
SUM(salary)
total
FROM
emp
GROUP
BY
dep)
SELECT
dep,
emp_id,
salary,
salary/ts.total*100
"%
of
dep"
FROM
emp
JOIN
total_salary_by_department
ts
ON
(emp.dep
=
ts.dep)
WHERE
emp.dep
=
?
WITH
total_salary_by_department
AS
(SELECT
dep,
SUM(salary)
total
FROM
emp
GROUP
BY
dep)
SELECT
dep,
emp_id,
salary,
salary/ts.total*100
"%
of
dep"
FROM
emp
JOIN
total_salary_by_department
ts
ON
(emp.dep
=
ts.dep)
WHERE
emp.dep
=
?
WITH
total_salary_by_department
AS
(SELECT
dep,
SUM(salary)
total
FROM
emp
GROUP
BY
dep)
SELECT
dep,
emp_id,
salary,
salary/ts.total*100
"%
of
dep"
FROM
emp
JOIN
total_salary_by_department
ts
ON
(emp.dep
=
ts.dep)
WHERE
emp.dep
=
?
Show
percentage
of
department
salary:
OVER Before SQL:2003
o
z
z
e
m
r
e
t
n
i
WITH
total_salary_by_department
H
T
I
W
AS
(SELECT
dep,
SUM(salary)
total
FROM
emp
GROUP
BY
dep)
SELECT
dep,
emp_id,
salary,
salary/ts.total*100
"%
of
dep"
FROM
emp
JOIN
total_salary_by_department
ts
ON
(emp.dep
=
ts.dep)
WHERE
emp.dep
=
?
dep salary
1
1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
dep salary
1
1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
dep salary
1
1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
dep salary
1
1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
dep salary
1
1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
dep salary
1
1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
ts
1000
2000
2000
3000
3000
3000
dep salary ts
T
dep,
1
1000 1000
salary,
22 1000 2000
SUM(salary)
22 1000 2000
OVER(PARTITION
BY
dep)
333
1000
3000
M
emp;
333 1000 3000
333 1000 3000
dep salary ts
T
dep,
1
1000 1000
salary,
22 1000 2000
SUM(salary)
22 1000 2000
OVER(PARTITION
BY
dep)
333
1000
3000
M
emp;
333 1000 3000
333 1000 3000
dep salary ts
T
dep,
1
1000 1000
salary,
22 1000 2000
SUM(salary)
22 1000 2000
OVER(PARTITION
BY
dep)
333
1000
3000
M
emp;
333 1000 3000
333 1000 3000
dep salary ts
T
dep,
1
1000 1000
salary,
22 1000 2000
SUM(salary)
22 1000 2000
OVER(PARTITION
BY
dep)
333
1000
3000
M
emp;
333 1000 3000
333 1000 3000
OVER in a Nutshell
OVER may follow any aggregate function
OVER defines which rows are visible at each row
(it does not limit the result in any way)
OVER() makes all rows visible at every row
OVER(PARTITION
BY x) segregates like GROUP
BY
OVER
and
ORDER BY
Do it in the application
ROW_NUMBER
Ranking functions:
RANK,
DENSE_RANK,
PERCENT_RANK,
CUME_DIST
&#'
('"#
)
*!+
,,
!"#$
%
#
WITHIN GROUP
Median
SELECT
PERCENTILE_DISC(0.5)
WITHIN
GROUP
(ORDER
BY
val)
FROM
data
...and hypothetical-set functions to say which rank
a hypothetical row would have:
SELECT
RANK(123)
WITHIN
GROUP
(ORDER
BY
val)
FROM
data
Median
SELECT
PERCENTILE_DISC(0.5)
WITHIN
GROUP
(ORDER
BY
val)
FROM
data
Which value?
...and hypothetical-set functions to say which rank
a hypothetical row would have:
SELECT
RANK(123)
WITHIN
GROUP
(ORDER
BY
val)
FROM
data
$ $
!"
#
!
SQL:2008
OVER
d
e
t
r
o
p
p
u
Not s
L
Q
S
e
r
g
by Post
Available functions:
LEAD
/
LAG
9.4)
f
o
s
a
(
FIRST_VALUE
/
LAST_VALUE
NTH_VALUE(col,
n)
FROM
FIRST/LAST
RESPECT/IGNORE
NULLS
!
'#
$
#(
'#
)*
+)%
$
"#$%
&
%
FETCH FIRST
SELECT
*
FROM
(SELECT
*,
ROW_NUMBER()
OVER(ORDER
BY
x)
rn
FROM
data)
numbered_data
WHERE
rn
<=10
'&"#
()#&!)
!*
!++
&),&#-
*!(
(
./)#&!)&#
%&+
/"&)$
SQL:2011
OFFSET
OFFSET is EVIL
http://use-the-index-luke.com/no-offset
OFFSET is EVIL
s
r
e !
k
c
i
s
t
r
e
s
t
b
s
a
a
r
o
G dc
an
http://use-the-index-luke.com/no-offset
2) ' -3/// ! *+ #( ' 0
WITHOUT OVERLAPS
id
begin
end
8:00
9:00
9:00
11:00
10:00 12:00
Temporal/Bi-Temporal SQL
SQL:2011 goes far beyond WITHOUT
OVERLAPS.
Please read these papers to get the idea:
Temporal features in SQL:2011
http://cs.ulb.ac.be/public/_media/teaching/infoh415/tempfeaturessql2011.pdf
"
$$
!
#
%
+
. %
/.
,.. 1
0,
&
'%
2,%#&
(
use-the-index-luke.com