Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent...
Transcript of Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent...
![Page 1: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/1.jpg)
Modern SQL:Evolution of a dinosaur
Markus Winand
Kraków, 9-11 May 2018
![Page 2: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/2.jpg)
Still using Windows 3.1? So why stick with
SQL-92?
@ModernSQL - https://modern-sql.com/ @MarkusWinand
![Page 3: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/3.jpg)
SQL:1999
![Page 4: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/4.jpg)
WITH (Common Table Expressions)
![Page 5: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/5.jpg)
Understand
this first
WITH (non-recursive) The ProblemNested queries are hard to read:
SELECT…FROM(SELECT…FROMt1JOIN(SELECT…FROM…)aON(…))bJOIN(SELECT…FROM…)cON(…)
![Page 6: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/6.jpg)
Then this...
WITH (non-recursive) The ProblemNested queries are hard to read:
SELECT…FROM(SELECT…FROMt1JOIN(SELECT…FROM…)aON(…))bJOIN(SELECT…FROM…)cON(…)
![Page 7: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/7.jpg)
Then this...
WITH (non-recursive) The ProblemNested queries are hard to read:
SELECT…FROM(SELECT…FROMt1JOIN(SELECT…FROM…)aON(…))bJOIN(SELECT…FROM…)cON(…)
![Page 8: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/8.jpg)
Finally the first line makes sense
WITH (non-recursive) The ProblemNested queries are hard to read:
SELECT…FROM(SELECT…FROMt1JOIN(SELECT…FROM…)aON(…))bJOIN(SELECT…FROM…)cON(…)
![Page 9: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/9.jpg)
CTEs are statement-scoped views:
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)
Keyword
WITH (non-recursive) Since SQL:1999
![Page 10: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/10.jpg)
CTEs are statement-scoped views:
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)
Name of CTE and (here optional) column names
WITH (non-recursive) Since SQL:1999
![Page 11: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/11.jpg)
CTEs are statement-scoped views:
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)
Definition
WITH (non-recursive) Since SQL:1999
![Page 12: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/12.jpg)
CTEs are statement-scoped views:
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)
Introduces another CTE
Don't repeat WITH
WITH (non-recursive) Since SQL:1999
![Page 13: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/13.jpg)
CTEs are statement-scoped views:
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)
May refer toprevious CTEs
WITH (non-recursive) Since SQL:1999
![Page 14: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/14.jpg)
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)AS(SELECT…FROM…)
SELECT…FROMbJOINcON(…)
Third CTE
WITH (non-recursive) Since SQL:1999
![Page 15: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/15.jpg)
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)AS(SELECT…FROM…)
SELECT…FROMbJOINcON(…)
No comma!
WITH (non-recursive) Since SQL:1999
![Page 16: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/16.jpg)
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)AS(SELECT…FROM…)
SELECT…FROMbJOINcON(…)
Main query
WITH (non-recursive) Since SQL:1999
![Page 17: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/17.jpg)
CTEs are statement-scoped views:
WITHa(c1,c2,c3)AS(SELECTc1,c2,c3FROM…),
b(c4,…)AS(SELECTc4,…FROMt1JOINaON(…)),
c(…)AS(SELECT…FROM…)
SELECT…FROMbJOINcON(…)
Read top down
WITH (non-recursive) Since SQL:1999
![Page 18: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/18.jpg)
‣ Literate SQL
Organize SQL code toimprove maintainability
‣ Assign column names
to tables produced by valuesor unnest.
‣ Overload tables (for testing)
with queries hide tablesof the same name.
Use-CasesWITH (non-recursive)
https://modern-sql.com/use-case/literate-sql
https://modern-sql.com/use-case/naming-unnamed-columns
https://modern-sql.com/use-case/unit-tests-on-transient-data
![Page 19: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/19.jpg)
WITH are the "private methods" of SQL
WITH is a prefix to SELECT
WITH queries are only visible in the SELECT they precede
WITH in detail: https://modern-sql.com/feature/with
WITH (non-recursive) In a Nutshell
![Page 20: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/20.jpg)
AvailabilityWITH (non-recursive)19
9920
0120
0320
0520
0720
0920
1120
1320
1520
17
5.1 10.2 MariaDB8.0 MySQL
8.4 PostgreSQL3.8.3[0] SQLite
7.0 DB2 LUW9iR2 Oracle
2005[1] SQL Server[0]Only for top-level SELECT statements[1]Only allowed at the very begin of a statement. E.g. WITH...INSERT...SELECT.
![Page 21: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/21.jpg)
WITHRECURSIVE (Common Table Expressions)
![Page 22: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/22.jpg)
(This page is intentionally left blank)
WITHRECURSIVE The Problem
![Page 23: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/23.jpg)
CREATETABLEt(idNUMERICNOTNULL,parent_idNUMERIC,…PRIMARYKEY(id))
Coping with hierarchies in the Adjacency List Model[0]
WITHRECURSIVE The Problem
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
![Page 24: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/24.jpg)
SELECT*FROMtASd0LEFTJOINtASd1ON(d1.parent_id=d0.id)LEFTJOINtASd2ON(d2.parent_id=d1.id)
Coping with hierarchies in the Adjacency List Model[0]
WITHRECURSIVE The Problem
WHEREd0.id=?
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
![Page 25: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/25.jpg)
SELECT*FROMtASd0LEFTJOINtASd1ON(d1.parent_id=d0.id)LEFTJOINtASd2ON(d2.parent_id=d1.id)
Coping with hierarchies in the Adjacency List Model[0]
WITHRECURSIVE The Problem
WHEREd0.id=?
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
![Page 26: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/26.jpg)
SELECT*FROMtASd0LEFTJOINtASd1ON(d1.parent_id=d0.id)LEFTJOINtASd2ON(d2.parent_id=d1.id)
WITHRECURSIVE Since SQL:1999
WHEREd0.id=?
WITHRECURSIVEd(id,parent,…)AS(SELECTid,parent,…FROMtblWHEREid=?UNIONALLSELECTid,parent,…FROMdJOINtblON(tbl.parent=d.id))SELECT*FROMsubtree
![Page 27: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/27.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
Keyword
Since SQL:1999WITHRECURSIVE
![Page 28: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/28.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
Column list mandatory here
Since SQL:1999WITHRECURSIVE
![Page 29: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/29.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
Executed first
Since SQL:1999WITHRECURSIVE
![Page 30: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/30.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
Result sent there
Since SQL:1999WITHRECURSIVE
![Page 31: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/31.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
Result visible twice
Since SQL:1999WITHRECURSIVE
![Page 32: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/32.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
Once it becomes
part of the final result
Since SQL:1999WITHRECURSIVE
![Page 33: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/33.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
Second leg of UNION is executed
Since SQL:1999WITHRECURSIVE
![Page 34: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/34.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
It's a loop!
Since SQL:1999WITHRECURSIVE
![Page 35: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/35.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
It's a loop!
Since SQL:1999WITHRECURSIVE
![Page 36: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/36.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
It's a loop!
Since SQL:1999WITHRECURSIVE
![Page 37: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/37.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
n=3 doesn't match
Since SQL:1999WITHRECURSIVE
![Page 38: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/38.jpg)
Recursive common table expressions may refer to themselves in a leg of a UNION[ALL]:
WITHRECURSIVEcte(n)AS(SELECT1UNIONALLSELECTn+1FROMcteWHEREn<3)SELECT*FROMcte
n---123(3rows)
n=3 doesn't matchLoop terminates
Since SQL:1999WITHRECURSIVE
![Page 39: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/39.jpg)
AvailabilityWITHRECURSIVE19
9920
0120
0320
0520
0720
0920
1120
1320
1520
17
5.1 10.2 MariaDB8.0 MySQL
8.4 PostgreSQL3.8.3[0] SQLite
7.0 DB2 LUW11gR2 Oracle
2005 SQL Server[0]Only for top-level SELECT statements
![Page 40: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/40.jpg)
SQL:2003
![Page 41: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/41.jpg)
OVER and
PARTITIONBY
![Page 42: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/42.jpg)
OVER (PARTITION BY) The ProblemTwo distinct concepts could not be used independently:
‣Merge rows with the same key properties
‣ GROUPBY to specify key properties
‣ DISTINCT to use full row as key
‣ Aggregate data from related rows ‣ Requires GROUPBY to segregate the rows
‣ COUNT, SUM, AVG, MIN, MAX to aggregate grouped rows
![Page 43: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/43.jpg)
SELECTc1,SUM(c2)totFROMtGROUPBYc1
OVER (PARTITION BY) The Problem
Yes ⇠
Mer
ge ro
ws ⇢
No
No ⇠ Aggregate ⇢ Yes
SELECTc1,c2FROMt
SELECTDISTINCTc1,c2FROMt
SELECTc1,c2FROMt
SELECTc1,SUM(c2)totFROMtGROUPBYc1
![Page 44: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/44.jpg)
SELECTc1,SUM(c2)totFROMtGROUPBYc1
OVER (PARTITION BY) The Problem
Yes ⇠
Mer
ge ro
ws ⇢
No
No ⇠ Aggregate ⇢ Yes
SELECTc1,c2FROMt
SELECTDISTINCTc1,c2FROMt
SELECTc1,c2FROMtJOIN()taON(t.c1=ta.c1)
SELECTc1,SUM(c2)totFROMtGROUPBYc1
,tot
![Page 45: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/45.jpg)
SELECTc1,SUM(c2)totFROMtGROUPBYc1
OVER (PARTITION BY) The Problem
Yes ⇠
Mer
ge ro
ws ⇢
No
No ⇠ Aggregate ⇢ Yes
SELECTc1,c2FROMt
SELECTDISTINCTc1,c2FROMt
SELECTc1,c2FROMtJOIN()taON(t.c1=ta.c1)
SELECTc1,SUM(c2)totFROMtGROUPBYc1
,tot
![Page 46: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/46.jpg)
SELECTc1,SUM(c2)totFROMtGROUPBYc1
OVER (PARTITION BY) Since SQL:2003
Yes ⇠
Mer
ge ro
ws ⇢
No
No ⇠ Aggregate ⇢ Yes
SELECTc1,c2FROMt
SELECTDISTINCTc1,c2FROMt
SELECTc1,c2FROMt
FROMt
,SUM(c2)OVER(PARTITIONBYc1)
![Page 47: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/47.jpg)
SELECTdep,salary,SUM(salary)OVER()FROMemp
dep salary ts1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000
OVER (PARTITION BY) How it works
![Page 48: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/48.jpg)
SELECTdep,salary,SUM(salary)OVER()FROMemp
dep salary ts1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000
OVER (PARTITION BY) How it works
![Page 49: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/49.jpg)
SELECTdep,salary,SUM(salary)OVER()FROMemp
dep salary ts1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000
OVER (PARTITION BY) How it works
![Page 50: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/50.jpg)
SELECTdep,salary,SUM(salary)OVER()FROMemp
dep salary ts1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000
OVER (PARTITION BY) How it works
![Page 51: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/51.jpg)
SELECTdep,salary,SUM(salary)OVER()FROMemp
dep salary ts1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000
OVER (PARTITION BY) How it works
![Page 52: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/52.jpg)
SELECTdep,salary,SUM(salary)OVER()FROMemp
dep salary ts1 1000 100022 1000 200022 1000 2000333 1000 3000333 1000 3000333 1000 3000
OVER (PARTITION BY) How it works
)PARTITIONBYdep
![Page 53: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/53.jpg)
OVER and
ORDERBY(Framing & Ranking)
![Page 54: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/54.jpg)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
OVER (ORDER BY) The Problem
SELECTid,value,FROMtransactionst
![Page 55: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/55.jpg)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
OVER (ORDER BY) The Problem
SELECTid,value,
(SELECTSUM(value)FROMtransactionst2WHEREt2.id<=t.id)
FROMtransactionst
![Page 56: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/56.jpg)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
OVER (ORDER BY) The Problem
SELECTid,value,
(SELECTSUM(value)FROMtransactionst2WHEREt2.id<=t.id)
FROMtransactionst
Range segregation (<=)not possible with
GROUP BY orPARTITION BY
![Page 57: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/57.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
![Page 58: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/58.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYid
![Page 59: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/59.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDING
![Page 60: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/60.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 61: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/61.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 62: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/62.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 63: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/63.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 64: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/64.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 65: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/65.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +30
22 3 -10 +20
333 4 +50 +70
333 5 -30 +40
333 6 -20 +20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 66: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/66.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10
22 2 +20
22 3 -10
333 4 +50
333 5 -30
333 6 -20
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
![Page 67: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/67.jpg)
OVER (ORDER BY) Since SQL:2003
SELECTid,value,
FROMtransactionst
SUM(value)OVER(
)
acnt id value balance
1 1 +10 +10
22 2 +20 +20
22 3 -10 +10
333 4 +50 +50
333 5 -30 +20
333 6 -20 .0
ORDERBYidROWSBETWEENUNBOUNDEDPRECEDINGANDCURRENTROW
PARTITIONBYacnt
![Page 68: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/68.jpg)
OVER (ORDER BY) Since SQL:2003With OVER(ORDERBYn) a new type of functions make sense:
n ROW_NUMBER RANK DENSE_RANK PERCENT_RANK CUME_DIST1 1 1 1 0 0.252 2 2 2 0.33… 0.753 3 2 2 0.33… 0.754 4 4 3 1 1
![Page 69: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/69.jpg)
‣ Aggregates without GROUPBY
‣ Running totals, moving averages
‣ Ranking‣ Top-N per Group
‣ Avoiding self-joins
[… many more …]
Use Cases
SELECT*FROM(SELECTROW_NUMBER()OVER(PARTITIONBY…ORDERBY…)rn,t.*FROMt)numbered_tWHERErn<=3
AVG(…)OVER(ORDERBY…ROWSBETWEEN3PRECEDINGAND3FOLLOWING)moving_avg
OVER (SQL:2003)
![Page 70: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/70.jpg)
OVER may follow any aggregate function
OVER defines which rows are visible at each row
OVER() makes all rows visible at every row
OVER(PARTITIONBY …) segregates like GROUPBY
OVER(ORDERBY…BETWEEN) segregates using <, >
In a NutshellOVER (SQL:2003)
![Page 71: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/71.jpg)
OVER (SQL:2003) Availability19
9920
0120
0320
0520
0720
0920
1120
1320
1520
17
5.1 10.2 MariaDB8.0 MySQL
8.4 PostgreSQLSQLite
7.0 DB2 LUW8i Oracle
2005 SQL Server
Hive
ImpalaSpark
NuoDB
![Page 72: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/72.jpg)
SQL:2006
![Page 73: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/73.jpg)
XMLTABLE
![Page 74: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/74.jpg)
SELECTid,c1,nFROMtbl,XMLTABLE('/d/e'PASSINGxCOLUMNSidINTPATH'@id',c1VARCHAR(255)PATH'c1',nFORORDINALITY)r
XMLTABLE Since SQL:2006Stored in tbl.x:
<d><eid="42"><c1>…</c1></e></d>
XPath* expression to identify rows
*Standard SQL allows XQuery
![Page 75: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/75.jpg)
SELECTid,c1,nFROMtbl,XMLTABLE('/d/e'PASSINGxCOLUMNSidINTPATH'@id',c1VARCHAR(255)PATH'c1',nFORORDINALITY)r
XMLTABLE Since SQL:2006Stored in tbl.x:
<d><eid="42"><c1>…</c1></e></d>
*Standard SQL allows XQuery
![Page 76: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/76.jpg)
SELECTid,c1,nFROMtbl,XMLTABLE('/d/e'PASSINGxCOLUMNSidINTPATH'@id',c1VARCHAR(255)PATH'c1',nFORORDINALITY)r
XMLTABLE Since SQL:2006Stored in tbl.x:
<d><eid="42"><c1>…</c1></e></d>
*Standard SQL allows XQuery
XPath* expressions to extract data
![Page 77: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/77.jpg)
SELECTid,c1,nFROMtbl,XMLTABLE('/d/e'PASSINGxCOLUMNSidINTPATH'@id',c1VARCHAR(255)PATH'c1',nFORORDINALITY)r
XMLTABLE Since SQL:2006Stored in tbl.x:
<d><eid="42"><c1>…</c1></e></d>
*Standard SQL allows XQuery
Row number (like for unnest)
![Page 78: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/78.jpg)
SELECTid,c1,nFROMtbl,XMLTABLE('/d/e'PASSINGxCOLUMNSidINTPATH'@id',c1VARCHAR(255)PATH'c1',nFORORDINALITY)r
XMLTABLE Since SQL:2006Stored in tbl.x:
<d><eid="42"><c1>…</c1></e></d>
*Standard SQL allows XQuery
Result id|c1|n----+----+---42|…|1
![Page 79: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/79.jpg)
XMLTABLE Availability19
99
2001
2003
2005
2007
2009
2011
2013
2015
2017
MariaDBMySQL
10[0] PostgreSQLSQLite
9.7 DB2 LUW11gR1 Oracle
SQL Server[0]No XQuery (only XPath). No default namespace declaration.
![Page 80: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/80.jpg)
SQL:2008
![Page 81: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/81.jpg)
FETCHFIRST
![Page 82: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/82.jpg)
SELECT*FROM(SELECT*,ROW_NUMBER()OVER(ORDERBYx)rnFROMdata)numbered_dataWHERErn<=10
FETCHFIRST The ProblemLimit the result to a number of rows. (LIMIT, TOP and ROWNUM are all proprietary)
SQL:2003 introduced ROW_NUMBER() to number rows.But this still requires wrapping to limit the result.
And how about databases not supporting ROW_NUMBER()?
![Page 83: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/83.jpg)
SELECT*FROM(SELECT*,ROW_NUMBER()OVER(ORDERBYx)rnFROMdata)numbered_dataWHERErn<=10
FETCHFIRST The ProblemLimit the result to a number of rows. (LIMIT, TOP and ROWNUM are all proprietary)
SQL:2003 introduced ROW_NUMBER() to number rows.But this still requires wrapping to limit the result.
And how about databases not supporting ROW_NUMBER()?
Dammit! Let's takeLIMIT
![Page 84: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/84.jpg)
SELECT*FROMdataORDERBYxFETCHFIRST10ROWSONLY
FETCHFIRST Since SQL:2008SQL:2008 introduced the FETCHFIRST…ROWSONLY clause:
![Page 85: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/85.jpg)
FETCHFIRST Availability19
99
2001
2003
2005
2007
2009
2011
2013
2015
2017
5.1 MariaDB3.19.3[0] MySQL
6.5[1] 8.4 PostgreSQL2.1.0[1] SQLite
7.0 DB2 LUW12cR1 Oracle
7.0[2] 2012 SQL Server[0]Earliest mention of LIMIT. Probably inherited from mSQL[1]Functionality available using LIMIT[2]SELECTTOPn... SQL Server 2000 also supports expressions and bind parameters
![Page 86: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/86.jpg)
SQL:2011
![Page 87: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/87.jpg)
OFFSET
![Page 88: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/88.jpg)
SELECT*FROM(SELECT*,ROW_NUMBER()OVER(ORDERBYx)rnFROMdata)numbered_dataWHERErn>10andrn<=20
OFFSET The ProblemHow to fetch the rows after a limit?
(pagination anybody?)
![Page 89: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/89.jpg)
SELECT*FROMdataORDERBYxOFFSET10ROWSFETCHNEXT10ROWSONLY
OFFSET Since SQL:2011SQL:2011 introduced OFFSET, unfortunately!
![Page 90: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/90.jpg)
SELECT*FROMdataORDERBYxOFFSET10ROWSFETCHNEXT10ROWSONLY
OFFSET Since SQL:2011SQL:2011 introduced OFFSET, unfortunately!
OFFSETGrab coasters & stickers!
https://use-the-index-luke.com/no-offset
![Page 91: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/91.jpg)
OFFSET Since SQL:201119
99
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB3.20.3[0] 4.0.6[1] MySQL
6.5 PostgreSQL2.1.0 SQLite
9.7[2] 11.1 DB2 LUW12c Oracle
2012 SQL Server[0]LIMIT[offset,]limit: "With this it's easy to do a poor man's next page/previous page WWW application."[1]The release notes say "Added PostgreSQL compatible LIMIT syntax"[2]Requires enabling the MySQL compatibility vector: db2setDB2_COMPATIBILITY_VECTOR=MYS
![Page 92: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/92.jpg)
OVER
![Page 93: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/93.jpg)
WITHnumbered_tAS(SELECT*)
SELECTcurr.*,curr.balance-COALESCE(prev.balance,0)FROMnumbered_tcurrLEFTJOINnumbered_tprevON(curr.rn=prev.rn+1)
OVER (SQL:2011) The ProblemDirect access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
currbalance … rn
50 … 190 … 270 … 330 … 4
FROMt
![Page 94: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/94.jpg)
WITHnumbered_tAS(SELECT*)
SELECTcurr.*,curr.balance-COALESCE(prev.balance,0)FROMnumbered_tcurrLEFTJOINnumbered_tprevON(curr.rn=prev.rn+1)
OVER (SQL:2011) The ProblemDirect access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
currbalance … rn
50 … 190 … 270 … 330 … 4
FROMt,ROW_NUMBER()OVER(ORDERBYx)rn
![Page 95: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/95.jpg)
WITHnumbered_tAS(SELECT*)
SELECTcurr.*,curr.balance-COALESCE(prev.balance,0)FROMnumbered_tcurrLEFTJOINnumbered_tprevON(curr.rn=prev.rn+1)
OVER (SQL:2011) The ProblemDirect access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
currbalance … rn
50 … 190 … 270 … 330 … 4
FROMt,ROW_NUMBER()OVER(ORDERBYx)rn
![Page 96: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/96.jpg)
WITHnumbered_tAS(SELECT*)
SELECTcurr.*,curr.balance-COALESCE(prev.balance,0)FROMnumbered_tcurrLEFTJOINnumbered_tprevON(curr.rn=prev.rn+1)
OVER (SQL:2011) The ProblemDirect access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
currbalance … rn
50 … 190 … 270 … 330 … 4
FROMt,ROW_NUMBER()OVER(ORDERBYx)rn
prevbalance … rn
50 … 190 … 270 … 330 … 4
![Page 97: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/97.jpg)
WITHnumbered_tAS(SELECT*)
SELECTcurr.*,curr.balance-COALESCE(prev.balance,0)FROMnumbered_tcurrLEFTJOINnumbered_tprevON(curr.rn=prev.rn+1)
OVER (SQL:2011) The ProblemDirect access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
currbalance … rn
50 … 190 … 270 … 330 … 4
FROMt,ROW_NUMBER()OVER(ORDERBYx)rn
prevbalance … rn
50 … 190 … 270 … 330 … 4
![Page 98: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/98.jpg)
WITHnumbered_tAS(SELECT*)
SELECTcurr.*,curr.balance-COALESCE(prev.balance,0)FROMnumbered_tcurrLEFTJOINnumbered_tprevON(curr.rn=prev.rn+1)
OVER (SQL:2011) The ProblemDirect access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
currbalance … rn
50 … 190 … 270 … 330 … 4
FROMt,ROW_NUMBER()OVER(ORDERBYx)rn
prevbalance … rn
50 … 190 … 270 … 330 … 4
+50+40-20-40
![Page 99: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/99.jpg)
SELECT*,balance-COALESCE(LAG(balance)OVER(ORDERBYx),0)FROMt
Available functions:LEAD/LAGFIRST_VALUE/LAST_VALUENTH_VALUE(col,n)FROMFIRST/LASTRESPECT/IGNORENULLS
OVER (SQL:2011) Since SQL:2011SQL:2011 introduced LEAD, LAG, NTH_VALUE, … for that:
![Page 100: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/100.jpg)
OVER (LEAD, LAG, …) Since SQL:201119
9920
0120
0320
0520
0720
0920
1120
1320
1520
17
5.1 10.2[0] MariaDB8.0[0] MySQL
8.4[0] PostgreSQLSQLite
9.5[1] 11.1 DB2 LUW8i[1] 11gR2 Oracle
2012[1] SQL Server[0]No IGNORENULLS and FROMLAST[1]No NTH_VALUE
![Page 101: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/101.jpg)
System Versioning (Time Traveling)
![Page 102: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/102.jpg)
INSERTUPDATEDELETE
are DESTRUCTIVE
System Versioning The Problem
![Page 103: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/103.jpg)
CREATETABLEt(...,start_tsTIMESTAMP(9)GENERATEDALWAYSASROWSTART,end_tsTIMESTAMP(9)GENERATEDALWAYSASROWEND,
PERIODFORSYSTEM_TIME(start_ts,end_ts))WITHSYSTEMVERSIONING
System Versioning Since SQL:2011Table can be system versioned, application versioned or both.
![Page 104: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/104.jpg)
ID Data start_ts end_ts1 X 10:00:00
UPDATE...SETDATA='Y'...
ID Data start_ts end_ts1 X 10:00:00 11:00:001 Y 11:00:00
DELETE...WHEREID=1
INSERT...(ID,DATA)VALUES(1,'X')
System Versioning Since SQL:2011
![Page 105: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/105.jpg)
ID Data start_ts end_ts1 X 10:00:00
UPDATE...SETDATA='Y'...
ID Data start_ts end_ts1 X 10:00:00 11:00:001 Y 11:00:00
DELETE...WHEREID=1
ID Data start_ts end_ts1 X 10:00:00 11:00:001 Y 11:00:00 12:00:00
INSERT...(ID,DATA)VALUES(1,'X')
System Versioning Since SQL:2011
![Page 106: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/106.jpg)
Although multiple versions exist, only the “current” one is visible per default.
After 12:00:00, SELECT*FROMt doesn’t return anything anymore.
ID Data start_ts end_ts1 X 10:00:00 11:00:001 Y 11:00:00 12:00:00
System Versioning Since SQL:2011
![Page 107: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/107.jpg)
ID Data start_ts end_ts1 X 10:00:00 11:00:001 Y 11:00:00 12:00:00
With FOR…ASOF you can query anything you like: SELECT*FROMtFORSYSTEM_TIMEASOFTIMESTAMP'2015-04-0210:30:00'
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
System Versioning Since SQL:2011
![Page 108: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/108.jpg)
1999
2001
2003
2005
2007
2009
2011
2013
2015
2017
5.1 MariaDB[0]
MySQLPostgreSQLSQLite
10.1[1] DB2 LUW10gR1[2] Oracle
2016 SQL Server[0]Available in MariaDB 10.3 beta.[1]Third column required (tx id), history table required.[2]Functionality available using Flashback
System Versioning Since SQL:2011
![Page 109: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/109.jpg)
SQL:2016 (released: 2016-12-15)
![Page 110: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/110.jpg)
LISTAGG
![Page 111: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/111.jpg)
Since SQL:2016
grp val1 B1 A1 C2 X
grp val1 A, B, C2 X
SELECTgrp,LISTAGG(val,',')WITHINGROUP(ORDERBYval)FROMtGROUPBYgrp
LISTAGG(val,','ONOVERFLOWTRUNCATE'...'WITHCOUNT)➔'A,B,...(1)'
LISTAGG(val,','ONOVERFLOWERROR)
Default
LISTAGG
LISTAGG(val,','ONOVERFLOWTRUNCATE'...'WITHOUTCOUNT)➔'A,B,...'
Default
![Page 112: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/112.jpg)
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0] MariaDB4.1[0] MySQL
7.4[1] 8.4[2]9.0[3] PostgreSQL3.5.4[4] SQLite
10.5[5] DB2 LUW11gR1 12cR2 Oracle
SQL Server[6]
[0]group_concat[1]array_to_string[2]array_agg[3]string_agg[4]group_concat without ORDER BY[5]No ON OVERFLOW clause[6]string_agg announced for vNext
LISTAGG Availability
[0] group_concat [1] array_to_string [2] array_agg [3] string_agg
[4] group_concat w/o ORDERBY [5] No ONOVERFLOW clause [6] string_agg announced for vNext
![Page 113: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/113.jpg)
New in SQL:2016 JSON
LISTAGGhttps://modern-sql.com/feature/listagg
ROW PATTERN MATCHING https://www.slideshare.net/MarkusWinand/row-pattern-matching-in-sql2016
DATE FORMAT POLYMORPHIC TABLE FUNCTIONS
➔ https://modern-sql.com/blog/2017-06/whats-new-in-sql-2016
![Page 114: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/114.jpg)
SQL has evolved beyond the relational idea.
Modern SQL? @MarkusWinand
![Page 115: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/115.jpg)
SQL has evolved beyond the relational idea.
If you are using SQL like 25 years ago,you are doing it wrong!
Modern SQL? @MarkusWinand
![Page 116: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/116.jpg)
SQL has evolved beyond the relational idea.
If you are using SQL like 25 years ago,you are doing it wrong!
A lot has happened since SQL-92.
Modern SQL? @MarkusWinand
![Page 117: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/117.jpg)
https://www.flickr.com/photos/mfoubister/25367243054/
![Page 118: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/118.jpg)
I have shown you a few features today
https://www.flickr.com/photos/mfoubister/25367243054/
![Page 119: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/119.jpg)
I have shown you a few features today
https://www.flickr.com/photos/mfoubister/25367243054/
There are hundreds more to discover
![Page 120: Modern SQL2018/05/10 · WITH RECURSIVE The Problem [0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties” SELECT](https://reader036.fdocuments.us/reader036/viewer/2022063001/5f1d90f063438250670c4a0c/html5/thumbnails/120.jpg)
@ModernSQL modern-sql.comMy other website:
https://use-the-index-luke.com
Training & co: https://winand.at/