167
Still using Windows 3.1? So why stick with SQL-92? @ModernSQL - https://modern-sql.com/ @MarkusWinand

Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

  • Upload
    others

  • View
    10

  • Download
    0

Embed Size (px)

Citation preview

Page 1: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Still using Windows 3.1? So why stick with

SQL-92?

@ModernSQL - https://modern-sql.com/ @MarkusWinand

Page 2: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:1999

Page 3: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

WITH (Common Table Expressions)

Page 4: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

WITH (non-recursive) The ProblemNested queries are hard to read:

SELECT…FROM(SELECT…FROMt1JOIN(SELECT…FROM…)aON(…))bJOIN(SELECT…FROM…)cON(…)

Page 5: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

‣ 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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

AvailabilityWITH (non-recursive)1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

WITHRECURSIVE (Common Table Expressions)

Page 22: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

(This page is intentionally left blank)

WITHRECURSIVE The Problem

Page 23: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 25: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 27: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 28: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 29: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 30: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 31: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 32: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 33: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 34: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 35: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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)

Since SQL:1999WITHRECURSIVE

Page 36: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 37: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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)

Result sent there again

Since SQL:1999WITHRECURSIVE

Page 38: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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)

Since SQL:1999WITHRECURSIVE

Page 39: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 40: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 41: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 42: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 43: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 44: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Use Cases‣ Row generators

To fill gaps (e.g., in time series), generate test data.

‣ Processing graphs

Shortest route from person A to B in LinkedIn/Facebook/Twitter/…

‣ Finding distinct values

with n*log(N)† time complexity. […many more…]

As shown on previous slide

http://aprogrammerwrites.eu/?p=1391

“[…] for certain classes of graphs, solutions utilizing relational database technology […] can offer performance superior to that of the dedicated graph databases.” event.cwi.nl/grades2013/07-welc.pdf

http://wiki.postgresql.org/wiki/Loose_indexscan

† n … # distinct values, N … # of table rows. Suitable index required

WITHRECURSIVE

Page 45: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

WITHRECURSIVE is the “while” of SQL

WITHRECURSIVE "supports" infinite loops

Except PostgreSQL, databases generally don't require the RECURSIVE keyword.

DB2, SQL Server & Oracle don’t even know the keyword RECURSIVE, but allow recursive CTEs anyway.

In a NutshellWITHRECURSIVE

Page 46: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

AvailabilityWITHRECURSIVE1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

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 47: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

GROUPINGSETS

Page 48: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Only one GROUPBY operation at a time:

GROUPINGSETS Before SQL:1999

SELECTyear,month,sum(revenue)FROMtblGROUPBYyear,month

Monthly revenue Yearly revenue

SELECTyear,sum(revenue)FROMtblGROUPBYyear

Page 49: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

GROUPINGSETS Before SQL:1999SELECTyear,month,sum(revenue)FROMtblGROUPBYyear,month

SELECTyear,sum(revenue)FROMtblGROUPBYyear

Page 50: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

GROUPINGSETS Before SQL:1999SELECTyear,month,sum(revenue)FROMtblGROUPBYyear,month

SELECTyear,sum(revenue)FROMtblGROUPBYyear

UNIONALL

,null

Page 51: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

GROUPINGSETS Since SQL:1999SELECTyear,month,sum(revenue)FROMtblGROUPBYyear,month

SELECTyear,sum(revenue)FROMtblGROUPBYyear

UNIONALL

,null

SELECTyear,month,sum(revenue)FROMtblGROUPBYGROUPINGSETS((year,month),(year))

Page 52: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

GROUPINGSETS are multiple GROUPBYs in one go

() (empty parenthesis) build a group over all rows

GROUPING (function) disambiguates the meaning of NULL(was the grouped data NULL or is this column not currently grouped?)

Permutations can be created using ROLLUP and CUBE(ROLLUP(a,b,c) = GROUPINGSETS((a,b,c),(a,b),(a),())

GROUPINGSETS In a Nutshell

Page 53: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

GROUPINGSETS Availability1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1[0] MariaDB5.0[1] MySQL

9.5 PostgreSQLSQLite

5 DB2 LUW9iR1 Oracle

2008 SQL Server[0]Only ROLLUP (properitery syntax).[1]Only ROLLUP (properitery syntax). GROUPING function since MySQL 8.0.

Page 54: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:2003

Page 55: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

OVER and

PARTITIONBY

Page 56: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 57: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 58: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 59: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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

Page 60: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 61: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 62: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 63: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTdep,salary,SUM(salary)OVER()FROMemp

dep salary1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000

OVER (PARTITION BY) How it works

Page 64: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTdep,salary,SUM(salary)OVER()FROMemp

dep salary1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000

OVER (PARTITION BY) How it works

Look here

Page 65: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTdep,salary,SUM(salary)OVER()FROMemp

dep salary1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000

OVER (PARTITION BY) How it works

Page 66: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTdep,salary,SUM(salary)OVER()FROMemp

dep salary1 1000 600022 1000 600022 1000 6000333 1000 6000333 1000 6000333 1000 6000

OVER (PARTITION BY) How it works

Page 67: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTdep,salary,SUM(salary)OVER()FROMemp

dep salary1 1000 100022 1000 200022 1000 2000333 1000 3000333 1000 3000333 1000 3000

OVER (PARTITION BY) How it works

)PARTITIONBYdep

Page 68: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

OVER and

ORDERBY(Framing & Ranking)

Page 69: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 70: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 71: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 72: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 73: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 74: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 75: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 76: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 77: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 78: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 79: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 80: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 81: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 82: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 83: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

‣ 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 84: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 85: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1 10.2 MariaDB8.0 MySQL

8.4 PostgreSQLSQLite[0]

7.0 DB2 LUW8i Oracle

2005 SQL Server[0]Expected for release 3.25.0 (available in snapshot release).

OVER (SQL:2003) AvailabilityHive

ImpalaSpark

NuoDB

Page 86: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

NULLSFIRST/LAST

Page 87: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

The sorting of NULL is implementation defined (some DBs sort NULL as great, others as very small value)

NULLS FIRST/LAST Before SQL:2003

SELECT…FROM…ORDERBYCOALESCE(nullable,?);

If you know a valuelarger/smaller than any

actual value…

Page 88: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

The sorting of NULL is implementation defined (some DBs sort NULL as great, others as very small value)

NULLS FIRST/LAST Before SQL:2003

SELECT…FROM…ORDERBYCOALESCE(nullable,?);

ORDERBYCASEWHENnullableISNULLTHEN0ELSE1END,nullable;

Using an extra sort keyto put NULL and NOT NULL

apart is more robust

This shows NULLs first (no matter if nullable

is sorted ASC or DESC)

Page 89: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:2003 introduced ORDERBY…NULLSFIRST/LAST

NULLS FIRST/LAST Since SQL:2003

SELECT…FROM…ORDERBYnullableNULLSFIRST

Note: PostgreSQL accepts NULLSFIRST/LAST in index definitions.

This returnsNULLs first

(for ASC and DESC)

Page 90: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

NULLS FIRST/LAST Since SQL:20031999

2001

2003

2005

2007

2009

2011

2013

2015

2017

MariaDB[0]

MySQL[0]

8.3[1] PostgreSQLSQLite[0]

11.1[1] DB2 LUW11gR1[1] Oracle

SQL Server[0][0]By default sorted as smallest[1]By default sorted as greatest

Page 91: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

FILTER

Page 92: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTYEAR,SUM(CASEWHENMONTH=1THENrevenueELSE0END)JAN,SUM(CASEWHENMONTH=2THENrevenueEND)FEB,…FROMsalesGROUPBYYEAR

FILTER The ProblemPivot table: Years on the Y axis, month on X:

Page 93: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTYEAR,SUM(CASEWHENMONTH=1THENrevenueELSE0END)JAN,SUM(CASEWHENMONTH=2THENrevenueEND)FEB,…FROMsalesGROUPBYYEAR

FILTER The ProblemPivot table: Years on the Y axis, month on X:

Optional:ELSE NULL is default

Aggregatesignore NULL*

*Exceptions:array_agg, json_objectagg, xmlagg See: https://modern-sql.com/concept/null#aggregates

Page 94: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTYEAR,SUM(CASEWHENMONTH=1THENrevenueELSE0END)JAN,SUM(CASEWHENMONTH=2THENrevenueEND)FEB,…FROMsalesGROUPBYYEAR

FILTER The ProblemPivot table: Years on the Y axis, month on X:

Page 95: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTYEAR,SUM(revenue)FILTER(WHEREMONTH=1)JAN,SUM(revenue)FILTER(WHEREMONTH=2)FEB,…FROMsalesGROUPBYYEAR;

FILTER Since SQL:2003SQL:2003 allows FILTER(WHERE…) after aggregates:

Page 96: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

FILTER Since SQL:2003

Year

2016

2016

2016

2016

2016

Month

1

2

3

...

12

Revenue

1

23

345

...

1234

Year

2016

Jan

1

Feb

23

Mar

345

...

...

Dec

1234

SUM(…) FILTE

R(WHERE …)

SUM(…)

FILTER(WHER

E month=2)

SUM(rev

enue) FILTER(WHERE

month=3)

SUM(rev

enue) FILTER(WHERE mo

nth=…)

SUM(rev

enue) FILTER(WHERE month=

12)

Pivot in SQL1. Use GROUP BY

to combine rows2. Use FILTER to pick

rows per column

See: https://modern-sql.com/use-case/pivot

Page 97: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

FILTER Availability1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1 MariaDBMySQL

9.4 PostgreSQLSQLite[0]

DB2 LUWOracleSQL Server

[0]Only with OVER clause

Page 98: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Inverse Distribution Functions (percentiles)

Page 99: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTd1.valFROMdatad1JOINdatad2ON(d1.val<d2.valOR(d1.val=d2.valANDd1.id<d2.id))GROUPBYd1.valHAVINGcount(*)=(SELECTFLOOR(COUNT(*)/2)FROMdatad3)

Inverse Distribution Functions The ProblemGrouped rows cannot be ordered prior aggregation.

(how to get the middle value (median) of a set)

Page 100: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTd1.valFROMdatad1JOINdatad2ON(d1.val<d2.valOR(d1.val=d2.valANDd1.id<d2.id))GROUPBYd1.valHAVINGcount(*)=(SELECTFLOOR(COUNT(*)/2)FROMdatad3)

Inverse Distribution Functions The ProblemGrouped rows cannot be ordered prior aggregation.

(how to get the middle value (median) of a set)

Number rows

Pick middle one

Page 101: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTd1.valFROMdatad1JOINdatad2ON(d1.val<d2.valOR(d1.val=d2.valANDd1.id<d2.id))GROUPBYd1.valHAVINGcount(*)=(SELECTFLOOR(COUNT(*)/2)FROMdatad3)

Inverse Distribution Functions The ProblemGrouped rows cannot be ordered prior aggregation.

(how to get the middle value (median) of a set)

Number rows

Pick middle one

Page 102: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTPERCENTILE_DISC(0.5)WITHINGROUP(ORDERBYval)FROMdata

Median

Which value?

Since SQL:2003Inverse Distribution Functions

Page 103: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

1

2

3

4

0 0.25 0.5 0.75 11

2

3

4

0 0.25 0.5 0.75 11

2

3

4

PERCENTILE_DISC0 0.25 0.5 0.75 1

1

2

3

4

PERCENTILE_DISC0 0.25 0.5 0.75 1

1

2

3

4

PERCENTILE_DISC(0.5)0 0.25 0.5 0.75 1

1

2

3

4

PERCENTILE_CONT

PERCENTILE_DISC(0.5)0 0.25 0.5 0.75 1

1

2

3

4

PERCENTILE_CONT(0.5)

PERCENTILE_DISC(0.5)

SELECTPERCENTILE_DISC(0.5)WITHINGROUP(ORDERBYval)FROMdata

Since SQL:2003Inverse Distribution Functions

Two variants: ‣ for discrete values (categories) ‣ for continuous values (linear interpolation)

Page 104: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Inverse Distribution Functions Availability1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1 10.3[0] MariaDBMySQL

9.4 PostgreSQLSQLite

11.1 DB2 LUW9iR1 Oracle

2012[0] SQL Server[0]Only as window function (requires OVER clause)

Page 105: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:2006

Page 106: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

XMLTABLE

Page 107: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 108: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 109: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 110: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 111: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 112: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

XMLTABLE Availability1999

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 113: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:2008

Page 114: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

FETCHFIRST

Page 115: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 116: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 117: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECT*FROMdataORDERBYxFETCHFIRST10ROWSONLY

FETCHFIRST Since SQL:2008SQL:2008 introduced the FETCHFIRST…ROWSONLY clause:

Page 118: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

FETCHFIRST Availability1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1 MariaDB3.19.3[0] MySQL6.5[1] 8.4 PostgreSQL

2.1.0[1] SQLite7.0 DB2 LUW

12cR1 Oracle7.0[2] 2012 SQL Server

[0]Earliest mention of LIMIT. Probably inherited from mSQL[1]Functionality available using LIMIT[2]SELECT TOP n ... SQL Server 2000 also supports expressions and bind parameters

Page 119: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:2011

Page 120: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

OFFSET

Page 121: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 122: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECT*FROMdataORDERBYxOFFSET10ROWSFETCHNEXT10ROWSONLY

OFFSET Since SQL:2011SQL:2011 introduced OFFSET, unfortunately!

Page 123: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECT*FROMdataORDERBYxOFFSET10ROWSFETCHNEXT10ROWSONLY

OFFSET Since SQL:2011SQL:2011 introduced OFFSET, unfortunately!

OFFSETGrab coasters & stickers!

https://use-the-index-luke.com/no-offset

Page 124: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 125: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

OVER

Page 126: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 127: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 128: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 129: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 130: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 131: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 132: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 133: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

OVER (LEAD, LAG, …) Since SQL:20111999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1 10.2[0] MariaDB8.0[0] MySQL

8.4[0] PostgreSQLSQLite[0]

9.5[1] 11.1 DB2 LUW8i[1] 11gR2 Oracle

2012[1] SQL Server[0]No IGNORENULLS and FROMLAST[1]No NTH_VALUE

Page 134: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

System Versioning (Time Traveling)

Page 135: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

INSERTUPDATEDELETE

are DESTRUCTIVE

System Versioning The Problem

Page 136: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 137: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 138: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 139: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 140: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 141: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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'2018-09-1210:30:00'

ID Data start_ts end_ts

1 X 10:00:00 11:00:00

System Versioning Since SQL:2011

Page 142: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

System Versioning Since SQL:20111999

2001

2003

2005

2007

2009

2011

2013

2015

2017

5.1 10.3[0] MariaDBMySQLPostgreSQLSQLite

10.1[1] DB2 LUW10gR1[2] Oracle

2016 SQL Server[0]Transaction time not immutable. See MDEV-16236.[1]Third column required (tx id), history table required.[2]Functionality available using Flashback

Page 143: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL:2016 (released: 2016-12-15)

Page 144: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

MATCH_RECOGNIZE (Row Pattern Matching)

Page 145: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Row Pattern Matching

Time

30 minutes

Example: Logfile

Page 146: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Row Pattern Matching

Example: Logfile

Time

30 minutes

Session 1 Session 2

Session 3

Session 4

Page 147: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Row Pattern Matching

Example: Logfile

Time

30 minutes

Session 1 Session 2

Session 3

Session 4

Example problem:

‣ Average session duration

Two approaches:

‣ Row pattern matching

‣ Start-of-group tagging

Page 148: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

Oracle doesn’t support avg on intervals — query doesn’t work as shown

Page 149: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

definecontinued

Oracle doesn’t support avg on intervals — query doesn’t work as shown

Page 150: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

Oracle doesn’t support avg on intervals — query doesn’t work as shown

undefinedpattern variable: matches any row

Page 151: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

any numberof “cont”

rows

Oracle doesn’t support avg on intervals — query doesn’t work as shown

Page 152: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

Very muchlike GROUP BY

Oracle doesn’t support avg on intervals — query doesn’t work as shown

Page 153: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

Very muchlike SELECT

Oracle doesn’t support avg on intervals — query doesn’t work as shown

Page 154: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTCOUNT(*)sessions,AVG(duration)avg_durationFROMlogMATCH_RECOGNIZE(ORDERBYtsMEASURESLAST(ts)-FIRST(ts)ASdurationONEROWPERMATCHPATTERN(anycont*)DEFINEcontASts<PREV(ts)+INTERVAL'30'minute)t

Since SQL:2016Row Pattern Matching

Time

30 minutes

Oracle doesn’t support avg on intervals — query doesn’t work as shown

Page 155: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Row Pattern Matching Before SQL:2016

Time

30 minutes

Now, let’s try using window functions

Page 156: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTcount(*)sessions,avg(duration)avg_durationFROM(SELECTMAX(ts)-MIN(ts)durationFROM(SELECTts,COUNT(grp_start)OVER(ORDERBYts)session_noFROM(SELECTts,CASEWHENts>=LAG(ts,1,DATE'1900-01-1')OVER(ORDERBYts)+INTERVAL'30'minuteTHEN1ENDgrp_startFROMlog)tagged)numberedGROUPBYsession_no)grouped

Row Pattern Matching Before SQL:2016

Time

30 minutes

Start-of-group tags

Page 157: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTcount(*)sessions,avg(duration)avg_durationFROM(SELECTMAX(ts)-MIN(ts)durationFROM(SELECTts,COUNT(grp_start)OVER(ORDERBYts)session_noFROM(SELECTts,CASEWHENts>=LAG(ts,1,DATE'1900-01-1')OVER(ORDERBYts)+INTERVAL'30'minuteTHEN1ENDgrp_startFROMlog)tagged)numberedGROUPBYsession_no)grouped

Row Pattern Matching Before SQL:2016

Time

30 minutes

number sessions

2222 2 33 3 44 42 3 41

Page 158: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SELECTcount(*)sessions,avg(duration)avg_durationFROM(SELECTMAX(ts)-MIN(ts)durationFROM(SELECTts,COUNT(grp_start)OVER(ORDERBYts)session_noFROM(SELECTts,CASEWHENts>=LAG(ts,1,DATE'1900-01-1')OVER(ORDERBYts)+INTERVAL'30'minuteTHEN1ENDgrp_startFROMlog)tagged)numberedGROUPBYsession_no)grouped

Row Pattern Matching Before SQL:2016

Time

30 minutes 2222 2 33 3 44 42 3 41

Page 159: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Row Pattern Matching Since SQL:2016

https://www.slideshare.net/MarkusWinand/row-pattern-matching-in-sql2016

Page 160: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

Row Pattern Matching Availability1999

2001

2003

2005

2007

2009

2011

2013

2015

2017

MariaDBMySQLPostgreSQLSQLiteDB2 LUW

12cR1 OracleSQL Server

Page 161: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

SQL has evolved beyond the relational idea.

Modern SQL? @MarkusWinand

Page 162: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 163: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

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 164: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

https://www.flickr.com/photos/mfoubister/25367243054/

Page 165: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

I have shown you a few features today

https://www.flickr.com/photos/mfoubister/25367243054/

Page 166: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

I have shown you a few features today

https://www.flickr.com/photos/mfoubister/25367243054/

There are hundreds more to discover

Page 167: Still using Windows 3.1? - modern-sql.com · ‣Literate SQL Organize SQL code to improve maintainability ‣Assign column names to tables produced by values or unnest. ‣Overload

@ModernSQL modern-sql.comMy other website:

https://use-the-index-luke.com

Training & co: https://winand.at/