SlideShare a Scribd company logo
1 of 174
Download to read offline
Still using
Windows 3.1?
So why stick to
SQL-92?
@ModernSQL - http://modern-sql.com/
@MarkusWinand
SQL:1999
LATERAL
Select-list sub-queries must be scalar[0]:
LATERAL Before SQL:1999
SELECT	…	
					,	(SELECT	column_1	
										FROM	t1	
									WHERE	t1.x	=	t2.y	
							)	AS	c	
		FROM	t2	
				…											
(an atomic quantity that can hold only one value at a time[1])
[0] Neglecting row values and other workarounds here; [1] https://en.wikipedia.org/wiki/Scalar
Select-list sub-queries must be scalar[0]:
LATERAL Before SQL:1999
SELECT	…	
					,	(SELECT	column_1	
										FROM	t1	
									WHERE	t1.x	=	t2.y	
							)	AS	c	
		FROM	t2	
				…											
(an atomic quantity that can hold only one value at a time[1])
[0] Neglecting row values and other workarounds here; [1] https://en.wikipedia.org/wiki/Scalar
✗,	column_2
More than

one column?
Syntax error
}
More than

one row?
Runtime error!
Lateral derived tables lift both limitations and can be correlated:
LATERAL Since SQL:1999
SELECT	…	
					,	ldt.*	
		FROM	t2	
		LEFT	JOIN	LATERAL	(SELECT	column_1,	column_2	
																							FROM	t1	
																						WHERE	t1.x	=	t2.y	
																				)	AS	ldt	
							ON	(true)	
				…
Lateral derived tables lift both limitations and can be correlated:
LATERAL Since SQL:1999
SELECT	…	
					,	ldt.*	
		FROM	t2	
		LEFT	JOIN	LATERAL	(SELECT	column_1,	column_2	
																							FROM	t1	
																						WHERE	t1.x	=	t2.y	
																				)	AS	ldt	
							ON	(true)	
				…											
“Derived table” means

it’s in the

FROM/JOIN clause
Still
“correlated”
Regular join
semantics
FROM	t	
	JOIN	LATERAL	(SELECT	…	
																	FROM	…	
																WHERE	t.c=…	
																ORDER	BY	…	
																LIMIT	10	
														)	derived_table
‣ Top-N per group


inside a lateral derived table

FETCH	FIRST (or LIMIT, TOP)

applies per row from left tables.
‣ Also useful to find most recent
news from several subscribed
topics (“multi-source top-N”).
Use-CasesLATERAL
Add proper index

for Top-N query
http://use-the-index-luke.com/sql/partial-results/top-n-queries
FROM	t	
	JOIN	LATERAL	(SELECT	…	
																	FROM	…	
																WHERE	t.c=…	
																ORDER	BY	…	
																LIMIT	10	
														)	derived_table
‣ Top-N per group


inside a lateral derived table

FETCH	FIRST (or LIMIT, TOP)

applies per row from left tables.
‣ Also useful to find most recent
news from several subscribed
topics (“multi-source top-N”).
‣ Table function arguments


(TABLE often implies LATERAL)

Use-CasesLATERAL
		
	FROM	t	
	JOIN	TABLE	(your_func(t.c))
LATERAL is the "for each" loop of SQL
LATERAL plays well with outer and cross joins	
LATERAL is great for Top-N subqueries
LATERAL can join table functions (unnest!)

LATERAL In a Nutshell
LATERAL Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
MySQL
9.3 PostgreSQL
SQLite
9.1 DB2 LUW
11gR1[0]
12c Oracle
2005[1]
SQL Server
[0]
Undocumented. Requires setting trace event 22829.
[1]
LATERAL is not supported as of SQL Server 2016 but [CROSS|OUTER]	APPLY can be used for the same effect.
GROUPING	SETS
Only one GROUP	BY operation at a time:
GROUPING	SETS Before SQL:1999
SELECT	year	
					,	month	
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year,	month											
Monthly revenue Yearly revenue
SELECT	year	
					
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year
GROUPING	SETS Before SQL:1999
SELECT	year	
					,	month	
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year,	month											
SELECT	year	
					
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year
GROUPING	SETS Before SQL:1999
SELECT	year	
					,	month	
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year,	month											
SELECT	year	
					
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year											
UNION	ALL	
				,	null
GROUPING	SETS Since SQL:1999
SELECT	year	
					,	month	
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year,	month											
SELECT	year	
					
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	year											
UNION	ALL	
				,	null
SELECT	year	
					,	month	
					,	sum(revenue)	
		FROM	tbl	
	GROUP	BY	
							GROUPING	SETS	(	
										(year,	month)	
								,	(year)	
							)
GROUPING	SETS are multiple GROUP	BYs in one go
() (empty brackets) 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) = GROUPING	SETS	((a,b,c),	(a,b),(a),())	
GROUPING	SETS In a Nutshell
GROUPING	SETS Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0]
MariaDB
5.0[0]
MySQL
9.5 PostgreSQL
SQLite
5 DB2 LUW
9iR1 Oracle
2008 SQL Server
[0]
Only ROLLUP
WITH
(Common Table Expressions)
WITH (non-recursive) The Problem
Nested queries are hard to read:
SELECT	…	
		FROM	(SELECT	…	
										FROM	t1	
										JOIN	(SELECT	…	FROM	…	
															)	a	ON	(…)	
							)	b	
		JOIN	(SELECT	…	FROM	…	
							)	c	ON	(…)
Understand
this first
WITH (non-recursive) The Problem
Nested queries are hard to read:
SELECT	…	
		FROM	(SELECT	…	
										FROM	t1	
										JOIN	(SELECT	…	FROM	…	
															)	a	ON	(…)	
							)	b	
		JOIN	(SELECT	…	FROM	…	
							)	c	ON	(…)
Then this...
WITH (non-recursive) The Problem
Nested queries are hard to read:
SELECT	…	
		FROM	(SELECT	…	
										FROM	t1	
										JOIN	(SELECT	…	FROM	…	
															)	a	ON	(…)	
							)	b	
		JOIN	(SELECT	…	FROM	…	
							)	c	ON	(…)
Then this...
WITH (non-recursive) The Problem
Nested queries are hard to read:
SELECT	…	
		FROM	(SELECT	…	
										FROM	t1	
										JOIN	(SELECT	…	FROM	…	
															)	a	ON	(…)	
							)	b	
		JOIN	(SELECT	…	FROM	…	
							)	c	ON	(…)
Finally the first line makes sense
WITH (non-recursive) The Problem
Nested queries are hard to read:
SELECT	…	
		FROM	(SELECT	…	
										FROM	t1	
										JOIN	(SELECT	…	FROM	…	
															)	a	ON	(…)	
							)	b	
		JOIN	(SELECT	…	FROM	…	
							)	c	ON	(…)
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
WITH (non-recursive) Since SQL:1999
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
Keyword
WITH (non-recursive) Since SQL:1999
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
Name of CTE and (here
optional) column names
WITH (non-recursive) Since SQL:1999
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
Definition
WITH (non-recursive) Since SQL:1999
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
Introduces
another CTE
Don't repeat
WITH
WITH (non-recursive) Since SQL:1999
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
May refer to

previous CTEs
WITH (non-recursive) Since SQL:1999
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
	c	(…)	
AS	(SELECT	…	FROM	…)	
SELECT	…	
		FROM	b	JOIN	c	ON	(…)
Third CTE
WITH (non-recursive) Since SQL:1999
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
	c	(…)	
AS	(SELECT	…	FROM	…)	
SELECT	…	
		FROM	b	JOIN	c	ON	(…)
No comma!
WITH (non-recursive) Since SQL:1999
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
	c	(…)	
AS	(SELECT	…	FROM	…)	
SELECT	…	
		FROM	b	JOIN	c	ON	(…)
Main query
WITH (non-recursive) Since SQL:1999
CTEs are statement-scoped views:
WITH	
	a	(c1,	c2,	c3)	
AS	(SELECT	c1,	c2,	c3	FROM	…),	
	b	(c4,	…)	
AS	(SELECT	c4,	…	
						FROM	t1	
						JOIN	a	
								ON	(…)	
			),	
	c	(…)	
AS	(SELECT	…	FROM	…)	
SELECT	…	
		FROM	b	JOIN	c	ON	(…)
Read
top down
WITH (non-recursive) Since SQL:1999
‣ Literate SQL


Organize SQL code to

improve maintainability
‣ Assign column names


to tables produced by values

or unnest.
‣ Overload tables (for testing)


with queries hide tables

of the same name.
Use-CasesWITH (non-recursive)
http://modern-sql.com/use-case/literate-sql
http://modern-sql.com/use-case/naming-unnamed-columns
http://modern-sql.com/use-case/unit-tests-on-transient-data
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:
http://modern-sql.com/feature/with
WITH (non-recursive) In a Nutshell
PostgreSQL “issues”WITH (non-recursive)
In PostgreSQL WITH queries are “optimizer fences”:



WITH	cte	AS

(SELECT	*

			FROM	news)

SELECT	*	

		FROM	cte

	WHERE	topic=1
CTE	Scan	on	cte	
	(rows=6370)	
	Filter:	topic	=	1	
	CTE	cte	
	->	Seq	Scan	on	news	
				(rows=10000001)
PostgreSQL “issues”WITH (non-recursive)
In PostgreSQL WITH queries are “optimizer fences”:



WITH	cte	AS

(SELECT	*

			FROM	news)

SELECT	*	

		FROM	cte

	WHERE	topic=1
CTE	Scan	on	cte	
	(rows=6370)	
	Filter:	topic	=	1	
	CTE	cte	
	->	Seq	Scan	on	news	
				(rows=10000001)
PostgreSQL “issues”WITH (non-recursive)
In PostgreSQL WITH queries are “optimizer fences”:



WITH	cte	AS

(SELECT	*

			FROM	news)

SELECT	*	

		FROM	cte

	WHERE	topic=1
CTE	Scan	on	cte	
	(rows=6370)	
	Filter:	topic	=	1	
	CTE	cte	
	->	Seq	Scan	on	news	
				(rows=10000001)
PostgreSQL “issues”WITH (non-recursive)
In PostgreSQL WITH queries are “optimizer fences”:



WITH	cte	AS

(SELECT	*

			FROM	news)

SELECT	*	

		FROM	cte

	WHERE	topic=1
CTE
doesn't
know about
the outer
filter
Views and derived tables support "predicate pushdown":



SELECT	*

		FROM	(SELECT	*

										FROM	news

							)	n

	WHERE	topic=1;
PostgreSQL “issues”WITH (non-recursive)
Views and derived tables support "predicate pushdown":



SELECT	*

		FROM	(SELECT	*

										FROM	news

							)	n

	WHERE	topic=1;
Bitmap	Heap	Scan	
on	news	(rows=6370)	
->Bitmap	Index	Scan	
		on	idx	(rows=6370)	
		Cond:	topic=1
PostgreSQL “issues”WITH (non-recursive)
PostgreSQL 9.1+ allows DML within WITH:


WITH	deleted_rows	AS	(

			DELETE	FROM	source_tbl

			RETURNING	*

)

INSERT	INTO	destination_tbl

SELECT	*	FROM	deleted_rows;
PostgreSQL ExtensionWITH (non-recursive)
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0]
MariaDB
MySQL[1]
8.4 PostgreSQL
3.8.3[2]
SQLite
7 DB2 LUW
9iR2 Oracle
2005 SQL Server
[0]
Available MariaDB 10.2 alpha
[1]
Announced for 8.0: http://www.percona.com/blog/2016/09/01/percona-live-europe-featured-talk-manyi-lu
[2]
Only for top-level SELECT statements
AvailabilityWITH (non-recursive)
WITH	RECURSIVE
(Common Table Expressions)
CREATE	TABLE	t	(	
			id	NUMERIC	NOT	NULL,	
			parent_id	NUMERIC,	
			…	
			PRIMARY	KEY	(id)	
)
Coping with hierarchies in the Adjacency List Model[0]
WITH	RECURSIVE The Problem
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
SELECT	*	
		FROM	t	AS	d0	
		LEFT	JOIN	t	AS	d1		
				ON	(d1.parent_id=d0.id)	
		LEFT	JOIN	t	AS	d2		
				ON	(d2.parent_id=d1.id)	
			
Coping with hierarchies in the Adjacency List Model[0]
WITH	RECURSIVE The Problem
WHERE	d0.id	=	?
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
SELECT	*	
		FROM	t	AS	d0	
		LEFT	JOIN	t	AS	d1		
				ON	(d1.parent_id=d0.id)	
		LEFT	JOIN	t	AS	d2		
				ON	(d2.parent_id=d1.id)	
			
Coping with hierarchies in the Adjacency List Model[0]
WITH	RECURSIVE The Problem
WHERE	d0.id	=	?
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
SELECT	*	
		FROM	t	AS	d0	
		LEFT	JOIN	t	AS	d1		
				ON	(d1.parent_id=d0.id)	
		LEFT	JOIN	t	AS	d2		
				ON	(d2.parent_id=d1.id)	
			
Coping with hierarchies in the Adjacency List Model[0]
WITH	RECURSIVE The Problem
WHERE	d0.id	=	?
[0] Hierarchies implemented using a “parent id” — see “Joe Celko’s Trees and Hierarchies in SQL for Smarties”
SELECT	*	
		FROM	t	AS	d0	
		LEFT	JOIN	t	AS	d1		
				ON	(d1.parent_id=d0.id)	
		LEFT	JOIN	t	AS	d2		
				ON	(d2.parent_id=d1.id)	
			
WITH	RECURSIVE Since SQL:1999
WHERE	d0.id	=	?
WITH	RECURSIVE	
			d	(id,	parent,	…)	AS

					(SELECT	id,	parent,	…	
								FROM	tbl	
							WHERE	id	=	?	
			UNION	ALL	
						SELECT	id,	parent,	…	
								FROM	d	
								LEFT	JOIN	tbl

										ON	(tbl.parent=d.id)	
					)	
SELECT	*	
		FROM	subtree
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
Keyword
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
Column list
mandatory here
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
Executed first
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
Result
sent there
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
Result
visible
twice
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
Once it becomes
part of

the final

result
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
Second

leg of
UNION 

is
executed
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
Result
sent there
again
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
It's a
loop!
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
It's a
loop!
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
It's a
loop!
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
n=3

doesn't
match
Since SQL:1999WITH	RECURSIVE
Recursive common table expressions may refer to
themselves in the second leg of a UNION	[ALL]:
WITH	RECURSIVE	cte	(n)	
		AS	(SELECT	1	
							UNION	ALL	
						SELECT	n+1	
								FROM	cte	
							WHERE	n	<	3)	
SELECT	*	FROM	cte
	n		
---	
	1	
	2	
	3	
(3	rows)
n=3

doesn't
match
Loop
terminates
Since SQL:1999WITH	RECURSIVE
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
WITH	RECURSIVE
WITH	RECURSIVE is the “while” of SQL
WITH	RECURSIVE "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 NutshellWITH	RECURSIVE
AvailabilityWITH	RECURSIVE
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0]
MariaDB
MySQL[1]
8.4 PostgreSQL
3.8.3[2]
SQLite
7 DB2 LUW
11gR2 Oracle
2005 SQL Server
[0]
Expected in 10.2.2
[1]
Announced for 8.0: http://www.percona.com/blog/2016/09/01/percona-live-europe-featured-talk-manyi-lu
[2]
Only for top-level SELECT statements
SQL:2003
FILTER
SELECT	YEAR,		
							SUM(CASE	WHEN	MONTH	=	1	THEN	sales

																															ELSE	0

												END)	JAN,	
							SUM(CASE	WHEN	MONTH	=	2	THEN	sales

																															ELSE	0

												END)	FEB,	…	
		FROM	sale_data	
	GROUP	BY	YEAR
FILTER The Problem
Pivot table: Years on the Y axis, month on X:
SELECT	YEAR,	
							SUM(sales)	FILTER	(WHERE	MONTH	=	1)	JAN,	
							SUM(sales)	FILTER	(WHERE	MONTH	=	2)	FEB,	
							…	
		FROM	sale_data	
	GROUP	BY	YEAR;
FILTER Since SQL:2003
SQL:2003 allows FILTER	(WHERE…) after aggregates:
FILTER Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
MySQL
9.4 PostgreSQL
SQLite
DB2 LUW
Oracle
SQL Server
OVER
and
PARTITION	BY
OVER (PARTITION BY) The Problem
Two distinct concepts could not be used independently:
‣ Merge rows with the same key properties
‣ GROUP	BY to specify key properties
‣ DISTINCT to use full row as key
‣ Aggregate data from related rows
‣ Requires GROUP	BY to segregate the rows
‣ COUNT, SUM, AVG, MIN, MAX to aggregate grouped rows
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
OVER (PARTITION BY) The Problem
Yes⇠Mergerows⇢No
No ⇠ Aggregate ⇢ Yes
SELECT	c1	
					,	c2	
		FROM	t
SELECT	DISTINCT	
							c1	
					,	c2	
		FROM	t
SELECT	c1	
					,	c2	
		FROM	t
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
OVER (PARTITION BY) The Problem
Yes⇠Mergerows⇢No
No ⇠ Aggregate ⇢ Yes
SELECT	c1	
					,	c2	
		FROM	t
SELECT	DISTINCT	
							c1	
					,	c2	
		FROM	t
SELECT	c1	
					,	c2	
		FROM	t
JOIN	(					)	ta	
		ON	(t.c1=ta.c1)
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
,	tot
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
OVER (PARTITION BY) The Problem
Yes⇠Mergerows⇢No
No ⇠ Aggregate ⇢ Yes
SELECT	c1	
					,	c2	
		FROM	t
SELECT	DISTINCT	
							c1	
					,	c2	
		FROM	t
SELECT	c1	
					,	c2	
		FROM	t
JOIN	(					)	ta	
		ON	(t.c1=ta.c1)
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
,	tot
SELECT	c1	
					,	SUM(c2)	tot	
		FROM	t	
	GROUP	BY	c1
OVER (PARTITION BY) Since SQL:2003
Yes⇠Mergerows⇢No
No ⇠ Aggregate ⇢ Yes
SELECT	c1	
					,	c2	
		FROM	t
SELECT	DISTINCT	
							c1	
					,	c2	
		FROM	t
SELECT	c1	
					,	c2	
		FROM	t
FROM	t
,	SUM(c2)	
		OVER	(PARTITION	BY	c1)
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
dep salary ts
1 1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
OVER (PARTITION BY) How it works
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
dep salary ts
1 1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
OVER (PARTITION BY) How it works
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
dep salary ts
1 1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
OVER (PARTITION BY) How it works
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
dep salary ts
1 1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
OVER (PARTITION BY) How it works
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
dep salary ts
1 1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
OVER (PARTITION BY) How it works
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
OVER (PARTITION BY) How it works
)
dep salary ts
1 1000 6000
22 1000 6000
22 1000 6000
333 1000 6000
333 1000 6000
333 1000 6000
SELECT	dep,		
							salary,	
							SUM(salary)	
							OVER()	
		FROM	emp
dep salary ts
1 1000 1000
22 1000 2000
22 1000 2000
333 1000 3000
333 1000 3000
333 1000 3000
OVER (PARTITION BY) How it works
)PARTITION	BY	dep
OVER
and
ORDER	BY	
(Framing & Ranking)
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
SELECT	id,	
							value,
	FROM	transactions	t
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
SELECT	id,	
							value,
(SELECT	SUM(value)	
			FROM	transactions	t2	
		WHERE	t2.id	<=	t.id)
	FROM	transactions	t
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
SELECT	id,	
							value,
(SELECT	SUM(value)	
			FROM	transactions	t2	
		WHERE	t2.id	<=	t.id)
	FROM	transactions	t
Range segregation (<=)

not possible with

GROUP BY or

PARTITION BY
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
OVER (ORDER BY) Since SQL:2003
SELECT	id,	
							value,
	FROM	transactions	t
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
ORDER	BY	id	
	ROWS	BETWEEN

						UNBOUNDED	PRECEDING	
		AND	CURRENT	ROW
PARTITION	BY	acnt
OVER (ORDER BY) Since SQL:2003
With OVER	(ORDER	BY	n) a new type of functions make sense:
n ROW_NUMBER RANK DENSE_RANK PERCENT_RANK CUME_DIST
1 1 1 1 0 0.25
2 2 2 2 0.33… 0.75
3 3 2 2 0.33… 0.75
4 4 4 3 1 1
‣ Aggregates without GROUP	BY
‣ Running totals,

moving averages
‣ Ranking
‣ Top-N per Group
‣ Avoiding self-joins
[… many more …]
Use Cases
SELECT	*	
		FROM	(SELECT	ROW_NUMBER()		
															OVER(PARTITION	BY	…	ORDER	BY	…)	rn	
													,	t.*	
										FROM	t)	numbered_t	
WHERE	rn	<=	3
AVG(…)	OVER(ORDER	BY	…	
													ROWS	BETWEEN	3	PRECEDING	
																						AND	3	FOLLOWING)	moving_avg
OVER(SQL:2003)
OVER may follow any aggregate function	
OVER defines which rows are visible at each row	
OVER() makes all rows visible at every row	
OVER(PARTITION	BY …) segregates like GROUP	BY	
OVER(ORDER	BY	…	BETWEEN) segregates using <, >
In a NutshellOVER(SQL:2003)
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0]
MariaDB
MySQL[1]
8.4 PostgreSQL
SQLite
7 DB2 LUW
8i Oracle
2005 SQL Server
[0]
Available MariaDB 10.2 alpha
[1]
On the roadmap: http://www.slideshare.net/ManyiLu/optimizer-percona-liveams2015/47
OVER(SQL:2003) Availability
Hive
Impala
Spark
NuoDB
WITHIN	GROUP
SELECT	d1.val	
		FROM	data	d1	
		JOIN	data	d2	
				ON	(d1.val	<	d2.val	
							OR	(d1.val=d2.val	AND	d1.id<d2.id))	
	GROUP	BY	d1.val	
HAVING	count(*)	=		
							(SELECT	FLOOR(COUNT(*)/2)	
										FROM	data	d3)
WITHIN	GROUP The Problem
Grouped rows cannot be ordered prior aggregation.
(how to get the middle value (median) of a set)
SELECT	d1.val	
		FROM	data	d1	
		JOIN	data	d2	
				ON	(d1.val	<	d2.val	
							OR	(d1.val=d2.val	AND	d1.id<d2.id))	
	GROUP	BY	d1.val	
HAVING	count(*)	=		
							(SELECT	FLOOR(COUNT(*)/2)	
										FROM	data	d3)
WITHIN	GROUP The Problem
Grouped rows cannot be ordered prior aggregation.
(how to get the middle value (median) of a set)
Number rows
Pick middle one
SELECT	d1.val	
		FROM	data	d1	
		JOIN	data	d2	
				ON	(d1.val	<	d2.val	
							OR	(d1.val=d2.val	AND	d1.id<d2.id))	
	GROUP	BY	d1.val	
HAVING	count(*)	=		
							(SELECT	FLOOR(COUNT(*)/2)	
										FROM	data	d3)
WITHIN	GROUP The Problem
Grouped rows cannot be ordered prior aggregation.
(how to get the middle value (median) of a set)
Number rows
Pick middle one
SELECT	d1.val	
		FROM	data	d1	
		JOIN	data	d2	
				ON	(d1.val	<	d2.val	
							OR	(d1.val=d2.val	AND	d1.id<d2.id))	
	GROUP	BY	d1.val	
HAVING	count(*)	=		
							(SELECT	FLOOR(COUNT(*)/2)	
										FROM	data	d3)
WITHIN	GROUP The Problem
Grouped rows cannot be ordered prior aggregation.
(how to get the middle value (median) of a set)
Number rows
Pick middle one
SELECT	PERCENTILE_DISC(0.5)	
							WITHIN	GROUP	(ORDER	BY	val)	
		FROM	data
Median
Which value?
WITHIN	GROUP Since 2013
SQL:2003 introduced ordered set functions:
SELECT	PERCENTILE_DISC(0.5)	
							WITHIN	GROUP	(ORDER	BY	val)	
		FROM	data
WITHIN	GROUP Since 2013
SQL:2003 introduced ordered set functions:
SELECT	RANK(123)

							WITHIN	GROUP	(ORDER	BY	val)

		FROM	data
…and hypothetical set-functions:
WITHIN	GROUP Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
MySQL
9.4 PostgreSQL
SQLite
DB2 LUW
9iR1 Oracle
2012[0]
SQL Server
[0]
Only as window function (OVER required). Feature request 728969 closed as "won't fix"
TABLESAMPLE
TABLESAMPLE Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
MySQL
9.5[0]
PostgreSQL
SQLite
8.2[0]
DB2 LUW
8i[0]
Oracle
2005[0]
SQL Server
[0]
Not for derived tables
SQL:2008
FETCH	FIRST
SELECT	*	
		FROM	(SELECT	*	
													,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn	
										FROM	data)	numbered_data	
	WHERE	rn	<=10
FETCH	FIRST The Problem
Limit 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()?
SELECT	*	
		FROM	(SELECT	*	
													,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn	
										FROM	data)	numbered_data	
	WHERE	rn	<=10
FETCH	FIRST The Problem
Limit 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 take

LIMIT
SELECT	*	
		FROM	data	
	ORDER	BY	x	
	FETCH	FIRST	10	ROWS	ONLY
FETCH	FIRST Since SQL:2008
SQL:2008 introduced the FETCH	FIRST	…	ROWS	ONLY clause:
FETCH	FIRST Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
3.19.3[0]
MySQL
6.5[1]
8.4 PostgreSQL
2.1.0[1]
SQLite
7 DB2 LUW
12c Oracle
7.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
SQL:2011
OFFSET
SELECT	*	
		FROM	(SELECT	*	
													,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn	
										FROM	data)	numbered_data	
	WHERE	rn	>	10	and	rn	<=	20
OFFSET The Problem
How to fetch the rows after a limit?

(pagination anybody?)
SELECT	*	
		FROM	data	
	ORDER	BY	x	
OFFSET	10	ROWS	
	FETCH	NEXT	10	ROWS	ONLY
OFFSET Since SQL:2011
SQL:2011 introduced OFFSET, unfortunately!
SELECT	*	
		FROM	data	
	ORDER	BY	x	
OFFSET	10	ROWS	
	FETCH	NEXT	10	ROWS	ONLY
OFFSET Since SQL:2011
SQL:2011 introduced OFFSET, unfortunately!
OFFSET
Grab coasters
& stickers!
http://use-the-index-luke.com/no-offset
OFFSET Since SQL:2011
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
3.20.3[0]
4.0.6[1]
MySQL
6.5 PostgreSQL
2.1.0 SQLite
9.7[2]
11.1 DB2 LUW
12c 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: db2set	DB2_COMPATIBILITY_VECTOR=MYS
OVER
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
WITH	numbered_t	AS	(SELECT	*	
																								
																												)	
SELECT	curr.*	
					,	curr.balance	
							-	COALESCE(prev.balance,0)	
		FROM						numbered_t	curr	
		LEFT	JOIN	numbered_t	prev	
				ON	(curr.rn	=	prev.rn+1)
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
curr
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
FROM	t
WITH	numbered_t	AS	(SELECT	*	
																								
																												)	
SELECT	curr.*	
					,	curr.balance	
							-	COALESCE(prev.balance,0)	
		FROM						numbered_t	curr	
		LEFT	JOIN	numbered_t	prev	
				ON	(curr.rn	=	prev.rn+1)
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
curr
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
FROM	t
,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn
WITH	numbered_t	AS	(SELECT	*	
																								
																												)	
SELECT	curr.*	
					,	curr.balance	
							-	COALESCE(prev.balance,0)	
		FROM						numbered_t	curr	
		LEFT	JOIN	numbered_t	prev	
				ON	(curr.rn	=	prev.rn+1)
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
curr
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
FROM	t
,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn
WITH	numbered_t	AS	(SELECT	*	
																								
																												)	
SELECT	curr.*	
					,	curr.balance	
							-	COALESCE(prev.balance,0)	
		FROM						numbered_t	curr	
		LEFT	JOIN	numbered_t	prev	
				ON	(curr.rn	=	prev.rn+1)
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
curr
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
FROM	t
,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn
prev
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
WITH	numbered_t	AS	(SELECT	*	
																								
																												)	
SELECT	curr.*	
					,	curr.balance	
							-	COALESCE(prev.balance,0)	
		FROM						numbered_t	curr	
		LEFT	JOIN	numbered_t	prev	
				ON	(curr.rn	=	prev.rn+1)
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
curr
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
FROM	t
,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn
prev
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
WITH	numbered_t	AS	(SELECT	*	
																								
																												)	
SELECT	curr.*	
					,	curr.balance	
							-	COALESCE(prev.balance,0)	
		FROM						numbered_t	curr	
		LEFT	JOIN	numbered_t	prev	
				ON	(curr.rn	=	prev.rn+1)
OVER (SQL:2011) The Problem
Direct access of other rows of the same window is not possible.
(E.g., calculate the difference to the previous rows)
curr
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
FROM	t
,	ROW_NUMBER()	OVER(ORDER	BY	x)	rn
prev
balance … rn
50 … 1
90 … 2
70 … 3
30 … 4
+50
+40
-20
-40
SELECT	*,	balance	

										-	COALESCE(	LAG(balance)

																					OVER(ORDER	BY	x)

																				,	0)

		FROM	t
Available functions:
														LEAD	/	LAG

							FIRST_VALUE	/	LAST_VALUE

	NTH_VALUE(col,	n)	FROM	FIRST/LAST

																			RESPECT/IGNORE	NULLS
OVER (SQL:2011) Since SQL:2011
SQL:2011 introduced LEAD, LAG, NTH_VALUE, … for that:
OVER (LEAD, LAG, …) Since SQL:2011
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0]
MariaDB
MySQL
8.4[1]
PostgreSQL
SQLite
9.5[2]
11.1 DB2 LUW
8i[2]
11gR2 Oracle
2012[2]
SQL Server
[0]
Not yet available in MariaDB 10.2.2 (alpha). MDEV-8091
[1]
No IGNORE	NULLS and FROM	LAST as of PostgreSQL 9.6
[2]
No NTH_VALUE
Temporal Tables
(Time Traveling)
INSERT	
UPDATE	
DELETE	
are
DESTRUCTIVE
Temporal Tables The Problem
CREATE	TABLE	t	(...,
	start_ts	TIMESTAMP(9)	GENERATED

										ALWAYS	AS	ROW	START,
	end_ts			TIMESTAMP(9)	GENERATED

										ALWAYS	AS	ROW	END,

	PERIOD	FOR	SYSTEM	TIME	(start_ts,	end_ts)
)	WITH	SYSTEM	VERSIONING
Temporal Tables Since SQL:2011
Table can be system versioned, application versioned or both.
ID Data start_ts end_ts
1 X 10:00:00
UPDATE	...	SET	DATA	=	'Y'	...
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
1 Y 11:00:00
DELETE	...	WHERE	ID	=	1
INSERT	...	(ID,	DATA)	VALUES	(1,	'X')
Temporal Tables Since SQL:2011
ID Data start_ts end_ts
1 X 10:00:00
UPDATE	...	SET	DATA	=	'Y'	...
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
1 Y 11:00:00
DELETE	...	WHERE	ID	=	1
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
1 Y 11:00:00 12:00:00
Temporal Tables Since SQL:2011
Although multiple versions exist, only the “current”
one is visible per default.
After 12:00:00, SELECT	*	FROM	t doesn’t return
anything anymore.
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
1 Y 11:00:00 12:00:00
Temporal Tables Since SQL:2011
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
1 Y 11:00:00 12:00:00
With FOR	…	AS	OF you can query anything you like:
SELECT	*	
		FROM	t	FOR	SYSTEM_TIME	AS	OF	
									TIMESTAMP	'2015-04-02	10:30:00'
ID Data start_ts end_ts
1 X 10:00:00 11:00:00
Temporal Tables Since SQL:2011
It isn’t possible to define constraints to avoid overlapping periods.
Workarounds are possible, but no fun: CREATE	TRIGGER
id begin end
1 8:00 9:00
1 9:00 11:00
1 10:00 12:00
Temporal Tables The Problem
SQL:2011 provides means to cope with temporal tables:



PRIMARY	KEY	(id,	period	WITHOUT	OVERLAPS)
Temporal Tables Since SQL:2011
Temporal support in SQL:2011 goes way further.
Please read this paper to get the idea:
Temporal features in SQL:2011
http://cs.ulb.ac.be/public/_media/teaching/infoh415/tempfeaturessql2011.pdf
Temporal Tables Since SQL:2011
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1 MariaDB
MySQL
PostgreSQL
SQLite
10.1 DB2 LUW
10gR1[0]
12cR1[1]
Oracle
2016[2]
SQL Server
[0]
Limited system versioning via Flashback
[1]
Limited application versioning added (e.g. no WITHOUT OVERLAPS)
[2]
Only system versioning
SQL:2016(released: 2016-12-14)
MATCH_RECOGNIZE
(Row Pattern Matching)
Row Pattern Matching
Example: Logfile
Row Pattern Matching
Time
30 minutes
Example: Logfile
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
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	PREV(ts)	
																										+	INTERVAL	'30'	minute		
							)	t
Since SQL:2016Row Pattern Matching
Time
30 minutes
define

continuation
Oracle doesn’t support avg on intervals — query doesn’t work as shown
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	PREV(ts)	
																										+	INTERVAL	'30'	minute		
							)	t
Since SQL:2016Row Pattern Matching
Time
30 minutes
undefined

pattern variable:
matches any row
Oracle doesn’t support avg on intervals — query doesn’t work as shown
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	PREV(ts)	
																										+	INTERVAL	'30'	minute		
							)	t
Since SQL:2016Row Pattern Matching
Time
30 minutes
any number

of “cont”

rows
Oracle doesn’t support avg on intervals — query doesn’t work as shown
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	PREV(ts)	
																										+	INTERVAL	'30'	minute		
							)	t
Since SQL:2016Row Pattern Matching
Time
30 minutes
Very much

like GROUP BY
Oracle doesn’t support avg on intervals — query doesn’t work as shown
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	PREV(ts)	
																										+	INTERVAL	'30'	minute		
							)	t
Since SQL:2016Row Pattern Matching
Time
30 minutes
Very much

like SELECT
Oracle doesn’t support avg on intervals — query doesn’t work as shown
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	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
SELECT	COUNT(*)	sessions	
					,	AVG(duration)	avg_duration	
		FROM	log	
							MATCH_RECOGNIZE(	
								ORDER	BY	ts	
								MEASURES	
									LAST(ts)	-	FIRST(ts)	AS	duration	
								ONE	ROW	PER	MATCH	
								PATTERN	(	new	cont*	)	
								DEFINE	cont	AS	ts	<	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
Row Pattern Matching Before SQL:2016
Time
30 minutes
Now, let’s try using window functions
SELECT	count(*)	sessions,	avg(duration)	avg_duration	
		FROM	(SELECT	MAX(ts)	-	MIN(ts)	duration	
										FROM	(SELECT	ts,	COUNT(grp_start)	OVER(ORDER	BY	ts)	session_no	
																		FROM	(SELECT	ts,	CASE	WHEN	ts	>=	LAG(	ts,	1,	DATE’1900-01-1'	)	
																																																			OVER(	ORDER	BY	ts	)	
																																																			+	INTERVAL	'30'	minute	
																																								THEN	1	
																																				END	grp_start	
																										FROM	log	
																							)	tagged	
															)	numbered	
									GROUP	BY	session_no	
							)	grouped
Row Pattern Matching Before SQL:2016
Time
30 minutes
Start-of-group
tags
SELECT	count(*)	sessions,	avg(duration)	avg_duration	
		FROM	(SELECT	MAX(ts)	-	MIN(ts)	duration	
										FROM	(SELECT	ts,	COUNT(grp_start)	OVER(ORDER	BY	ts)	session_no	
																		FROM	(SELECT	ts,	CASE	WHEN	ts	>=	LAG(	ts,	1,	DATE’1900-01-1'	)	
																																																			OVER(	ORDER	BY	ts	)	
																																																			+	INTERVAL	'30'	minute	
																																								THEN	1	
																																				END	grp_start	
																										FROM	log	
																							)	tagged	
															)	numbered	
									GROUP	BY	session_no	
							)	grouped
Row Pattern Matching Before SQL:2016
Time
30 minutes
number
sessions
2222 2 33 3 44 42 3 4
1
SELECT	count(*)	sessions,	avg(duration)	avg_duration	
		FROM	(SELECT	MAX(ts)	-	MIN(ts)	duration	
										FROM	(SELECT	ts,	COUNT(grp_start)	OVER(ORDER	BY	ts)	session_no	
																		FROM	(SELECT	ts,	CASE	WHEN	ts	>=	LAG(	ts,	1,	DATE’1900-01-1'	)	
																																																			OVER(	ORDER	BY	ts	)	
																																																			+	INTERVAL	'30'	minute	
																																								THEN	1	
																																				END	grp_start	
																										FROM	log	
																							)	tagged	
															)	numbered	
									GROUP	BY	session_no	
							)	grouped
Row Pattern Matching Before SQL:2016
Time
30 minutes 2222 2 33 3 44 42 3 4
1
Row Pattern Matching Since SQL:2016
https://www.slideshare.net/MarkusWinand/row-pattern-matching-in-sql2016
Row Pattern Matching Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
MariaDB
MySQL
PostgreSQL
SQLite
DB2 LUW
12cR1 Oracle
SQL Server
LIST_AGG
Since SQL:2016
grp val
1 B
1 A
1 C
2 X
LIST_AGG
Since SQL:2016
grp val
1 B
1 A
1 C
2 X
SELECT	grp	
					,	LIST_AGG(val,	',	')

							WITHIN	GROUP	(ORDER	BY	val)	
		FROM	t	
	GROUP	BY	grp
LIST_AGG
Since SQL:2016
grp val
1 B
1 A
1 C
2 X
grp val
1 A, B, C
2 X
SELECT	grp	
					,	LIST_AGG(val,	',	')

							WITHIN	GROUP	(ORDER	BY	val)	
		FROM	t	
	GROUP	BY	grp
LIST_AGG
Since SQL:2016
grp val
1 B
1 A
1 C
2 X
grp val
1 A, B, C
2 X
SELECT	grp	
					,	LIST_AGG(val,	',	')

							WITHIN	GROUP	(ORDER	BY	val)	
		FROM	t	
	GROUP	BY	grp
LIST_AGG(val,	',	'	ON	OVERFLOW	TRUNCATE	'...'	WITH	COUNT)	➔	'A,	B,	...(1)'
LIST_AGG(val,	',	'	ON	OVERFLOW	ERROR)
Default
LIST_AGG
LIST_AGG(val,	',	'	ON	OVERFLOW	TRUNCATE	'...'	WITHOUT	COUNT)	➔	'A,	B,	...'
Default
LIST_AGG Availability
1999
2001
2003
2005
2007
2009
2011
2013
2015
5.1[0]
MariaDB
4.1[0]
MySQL
7.4[1]
8.4[2]
9.0[3]
PostgreSQL
3.5.4[4]
SQLite
10.5[5]
DB2 LUW
11gR1 12cR2 Oracle
SQL Server[6]
[0]
group_concat
[1]
array_to_string
[2]
array_agg
[3]
[0] group_concat
[1] array_to_string
[2] array_agg
[3] string_agg
[4] group_concat w/o ORDER	BY
[5] No ON	OVERFLOW clause
[6] string_agg announced for vNext
Also new in SQL:2016
JSON
DATE FORMAT
POLYMORPHIC TABLE FUNCTIONS
About @MarkusWinand
‣Training for Developers
‣ SQL Performance (Indexing)
‣ Modern SQL
‣ On-Site or Online
‣SQL Tuning
‣ Index-Redesign
‣ Query Improvements
‣ On-Site or Online
http://winand.at/
About @MarkusWinand
€0,-
€10-30
sql-performance-explained.com
About @MarkusWinand
@ModernSQL
http://modern-sql.com

More Related Content

What's hot

MySQL: Indexing for Better Performance
MySQL: Indexing for Better PerformanceMySQL: Indexing for Better Performance
MySQL: Indexing for Better Performancejkeriaki
 
Querying XML: XPath and XQuery
Querying XML: XPath and XQueryQuerying XML: XPath and XQuery
Querying XML: XPath and XQueryKatrien Verbert
 
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI Mansouri Khalifa
 
BigData_TP2: Design Patterns dans Hadoop
BigData_TP2: Design Patterns dans HadoopBigData_TP2: Design Patterns dans Hadoop
BigData_TP2: Design Patterns dans HadoopLilia Sfaxi
 
Query optimization
Query optimizationQuery optimization
Query optimizationNeha Behl
 
Introduction to structured query language (sql)
Introduction to structured query language (sql)Introduction to structured query language (sql)
Introduction to structured query language (sql)Sabana Maharjan
 
Database/ Bases de données
Database/ Bases de donnéesDatabase/ Bases de données
Database/ Bases de donnéeszied kallel
 
Beyond SQL: Speeding up Spark with DataFrames
Beyond SQL: Speeding up Spark with DataFramesBeyond SQL: Speeding up Spark with DataFrames
Beyond SQL: Speeding up Spark with DataFramesDatabricks
 
Indexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuningIndexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuningOSSCube
 
MongoDB, E-commerce and Transactions
MongoDB, E-commerce and TransactionsMongoDB, E-commerce and Transactions
MongoDB, E-commerce and TransactionsSteven Francia
 
SQL window functions for MySQL
SQL window functions for MySQLSQL window functions for MySQL
SQL window functions for MySQLDag H. Wanvik
 
Sql clauses by Manan Pasricha
Sql clauses by Manan PasrichaSql clauses by Manan Pasricha
Sql clauses by Manan PasrichaMananPasricha
 

What's hot (20)

MySQL: Indexing for Better Performance
MySQL: Indexing for Better PerformanceMySQL: Indexing for Better Performance
MySQL: Indexing for Better Performance
 
Bundling & minification
Bundling & minificationBundling & minification
Bundling & minification
 
Querying XML: XPath and XQuery
Querying XML: XPath and XQueryQuerying XML: XPath and XQuery
Querying XML: XPath and XQuery
 
Stored procedure
Stored procedureStored procedure
Stored procedure
 
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
Cours les Listes doublement chainées Prof. KHALIFA MANSOURI
 
BigData_TP2: Design Patterns dans Hadoop
BigData_TP2: Design Patterns dans HadoopBigData_TP2: Design Patterns dans Hadoop
BigData_TP2: Design Patterns dans Hadoop
 
noSQL
noSQLnoSQL
noSQL
 
Datastage ppt
Datastage pptDatastage ppt
Datastage ppt
 
Introduction to D3.js
Introduction to D3.jsIntroduction to D3.js
Introduction to D3.js
 
Query optimization
Query optimizationQuery optimization
Query optimization
 
Introduction to structured query language (sql)
Introduction to structured query language (sql)Introduction to structured query language (sql)
Introduction to structured query language (sql)
 
Database/ Bases de données
Database/ Bases de donnéesDatabase/ Bases de données
Database/ Bases de données
 
Beyond SQL: Speeding up Spark with DataFrames
Beyond SQL: Speeding up Spark with DataFramesBeyond SQL: Speeding up Spark with DataFrames
Beyond SQL: Speeding up Spark with DataFrames
 
Indexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuningIndexing the MySQL Index: Key to performance tuning
Indexing the MySQL Index: Key to performance tuning
 
MongodB Internals
MongodB InternalsMongodB Internals
MongodB Internals
 
MySQL ppt
MySQL ppt MySQL ppt
MySQL ppt
 
MongoDB, E-commerce and Transactions
MongoDB, E-commerce and TransactionsMongoDB, E-commerce and Transactions
MongoDB, E-commerce and Transactions
 
SQL window functions for MySQL
SQL window functions for MySQLSQL window functions for MySQL
SQL window functions for MySQL
 
Sql clauses by Manan Pasricha
Sql clauses by Manan PasrichaSql clauses by Manan Pasricha
Sql clauses by Manan Pasricha
 
Basic sql Commands
Basic sql CommandsBasic sql Commands
Basic sql Commands
 

Similar to Modern SQL in Open Source and Commercial Databases

Most useful queries
Most useful queriesMost useful queries
Most useful queriesSam Depp
 
从 Oracle 合并到 my sql npr 实例分析
从 Oracle 合并到 my sql   npr 实例分析从 Oracle 合并到 my sql   npr 实例分析
从 Oracle 合并到 my sql npr 实例分析YUCHENG HU
 
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgradeDevelopers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrademCloud
 
SQL Server Select Topics
SQL Server Select TopicsSQL Server Select Topics
SQL Server Select TopicsJay Coskey
 
xii-ip-support-material.pdf
xii-ip-support-material.pdfxii-ip-support-material.pdf
xii-ip-support-material.pdfkajalkhorwal106
 
Including Constraints -Oracle Data base
Including Constraints -Oracle Data base Including Constraints -Oracle Data base
Including Constraints -Oracle Data base Salman Memon
 
Sql overview-1232931296681161-1
Sql overview-1232931296681161-1Sql overview-1232931296681161-1
Sql overview-1232931296681161-1sagaroceanic11
 
Proc SQL in SAS Enterprise Guide 4.3
Proc SQL in SAS Enterprise Guide 4.3Proc SQL in SAS Enterprise Guide 4.3
Proc SQL in SAS Enterprise Guide 4.3Mark Tabladillo
 
Introduction to Oracle Database.pptx
Introduction to Oracle Database.pptxIntroduction to Oracle Database.pptx
Introduction to Oracle Database.pptxSiddhantBhardwaj26
 
this is about databases questions , maybe i miss copy some option D,.docx
this is about databases questions , maybe i miss copy some option D,.docxthis is about databases questions , maybe i miss copy some option D,.docx
this is about databases questions , maybe i miss copy some option D,.docxEvonCanales257
 
Oracle sql tutorial
Oracle sql tutorialOracle sql tutorial
Oracle sql tutorialMohd Tousif
 
Chapter – 6 SQL Lab Tutorial.pdf
Chapter – 6 SQL Lab Tutorial.pdfChapter – 6 SQL Lab Tutorial.pdf
Chapter – 6 SQL Lab Tutorial.pdfTamiratDejene1
 
SQL-8 Table Creation.pdf
SQL-8 Table Creation.pdfSQL-8 Table Creation.pdf
SQL-8 Table Creation.pdfHannanKhalid4
 

Similar to Modern SQL in Open Source and Commercial Databases (20)

Vertica-Database
Vertica-DatabaseVertica-Database
Vertica-Database
 
Most useful queries
Most useful queriesMost useful queries
Most useful queries
 
SQL Overview
SQL OverviewSQL Overview
SQL Overview
 
从 Oracle 合并到 my sql npr 实例分析
从 Oracle 合并到 my sql   npr 实例分析从 Oracle 合并到 my sql   npr 实例分析
从 Oracle 合并到 my sql npr 实例分析
 
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgradeDevelopers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
Developers’ mDay 2019. - Bogdan Kecman, Oracle – MySQL 8.0 – why upgrade
 
Sq lite module5
Sq lite module5Sq lite module5
Sq lite module5
 
SQL Server Select Topics
SQL Server Select TopicsSQL Server Select Topics
SQL Server Select Topics
 
xii-ip-support-material.pdf
xii-ip-support-material.pdfxii-ip-support-material.pdf
xii-ip-support-material.pdf
 
Including Constraints -Oracle Data base
Including Constraints -Oracle Data base Including Constraints -Oracle Data base
Including Constraints -Oracle Data base
 
SQL Notes
SQL NotesSQL Notes
SQL Notes
 
Sql overview-1232931296681161-1
Sql overview-1232931296681161-1Sql overview-1232931296681161-1
Sql overview-1232931296681161-1
 
Proc SQL in SAS Enterprise Guide 4.3
Proc SQL in SAS Enterprise Guide 4.3Proc SQL in SAS Enterprise Guide 4.3
Proc SQL in SAS Enterprise Guide 4.3
 
Introduction to Oracle Database.pptx
Introduction to Oracle Database.pptxIntroduction to Oracle Database.pptx
Introduction to Oracle Database.pptx
 
Oracle NOLOGGING
Oracle NOLOGGINGOracle NOLOGGING
Oracle NOLOGGING
 
this is about databases questions , maybe i miss copy some option D,.docx
this is about databases questions , maybe i miss copy some option D,.docxthis is about databases questions , maybe i miss copy some option D,.docx
this is about databases questions , maybe i miss copy some option D,.docx
 
Oracle sql tutorial
Oracle sql tutorialOracle sql tutorial
Oracle sql tutorial
 
SQL
SQLSQL
SQL
 
Chapter – 6 SQL Lab Tutorial.pdf
Chapter – 6 SQL Lab Tutorial.pdfChapter – 6 SQL Lab Tutorial.pdf
Chapter – 6 SQL Lab Tutorial.pdf
 
Oracle 10g
Oracle 10gOracle 10g
Oracle 10g
 
SQL-8 Table Creation.pdf
SQL-8 Table Creation.pdfSQL-8 Table Creation.pdf
SQL-8 Table Creation.pdf
 

More from Markus Winand

Standard SQL features where PostgreSQL beats its competitors
Standard SQL features where PostgreSQL beats its competitorsStandard SQL features where PostgreSQL beats its competitors
Standard SQL features where PostgreSQL beats its competitorsMarkus Winand
 
Four* Major Database Releases of 2017 in Review
Four* Major Database Releases of 2017 in ReviewFour* Major Database Releases of 2017 in Review
Four* Major Database Releases of 2017 in ReviewMarkus Winand
 
Row Pattern Matching in SQL:2016
Row Pattern Matching in SQL:2016Row Pattern Matching in SQL:2016
Row Pattern Matching in SQL:2016Markus Winand
 
SQL Transactions - What they are good for and how they work
SQL Transactions - What they are good for and how they workSQL Transactions - What they are good for and how they work
SQL Transactions - What they are good for and how they workMarkus Winand
 
Backend to Frontend: When database optimization affects the full stack
Backend to Frontend: When database optimization affects the full stackBackend to Frontend: When database optimization affects the full stack
Backend to Frontend: When database optimization affects the full stackMarkus Winand
 
Volkskrankheit "Stiefmuetterliche Indizierung"
Volkskrankheit "Stiefmuetterliche Indizierung"Volkskrankheit "Stiefmuetterliche Indizierung"
Volkskrankheit "Stiefmuetterliche Indizierung"Markus Winand
 
SQL Performance - Vienna System Architects Meetup 20131202
SQL Performance - Vienna System Architects Meetup 20131202SQL Performance - Vienna System Architects Meetup 20131202
SQL Performance - Vienna System Architects Meetup 20131202Markus Winand
 
Indexes: The neglected performance all rounder
Indexes: The neglected performance all rounderIndexes: The neglected performance all rounder
Indexes: The neglected performance all rounderMarkus Winand
 
Pagination Done the Right Way
Pagination Done the Right WayPagination Done the Right Way
Pagination Done the Right WayMarkus Winand
 

More from Markus Winand (9)

Standard SQL features where PostgreSQL beats its competitors
Standard SQL features where PostgreSQL beats its competitorsStandard SQL features where PostgreSQL beats its competitors
Standard SQL features where PostgreSQL beats its competitors
 
Four* Major Database Releases of 2017 in Review
Four* Major Database Releases of 2017 in ReviewFour* Major Database Releases of 2017 in Review
Four* Major Database Releases of 2017 in Review
 
Row Pattern Matching in SQL:2016
Row Pattern Matching in SQL:2016Row Pattern Matching in SQL:2016
Row Pattern Matching in SQL:2016
 
SQL Transactions - What they are good for and how they work
SQL Transactions - What they are good for and how they workSQL Transactions - What they are good for and how they work
SQL Transactions - What they are good for and how they work
 
Backend to Frontend: When database optimization affects the full stack
Backend to Frontend: When database optimization affects the full stackBackend to Frontend: When database optimization affects the full stack
Backend to Frontend: When database optimization affects the full stack
 
Volkskrankheit "Stiefmuetterliche Indizierung"
Volkskrankheit "Stiefmuetterliche Indizierung"Volkskrankheit "Stiefmuetterliche Indizierung"
Volkskrankheit "Stiefmuetterliche Indizierung"
 
SQL Performance - Vienna System Architects Meetup 20131202
SQL Performance - Vienna System Architects Meetup 20131202SQL Performance - Vienna System Architects Meetup 20131202
SQL Performance - Vienna System Architects Meetup 20131202
 
Indexes: The neglected performance all rounder
Indexes: The neglected performance all rounderIndexes: The neglected performance all rounder
Indexes: The neglected performance all rounder
 
Pagination Done the Right Way
Pagination Done the Right WayPagination Done the Right Way
Pagination Done the Right Way
 

Recently uploaded

Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...OnePlan Solutions
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxSasikiranMarri
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolsosttopstonverter
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldRoberto Pérez Alcolea
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfkalichargn70th171
 
Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...
Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...
Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...OnePlan Solutions
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?Alexandre Beguel
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptxVinzoCenzo
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...Bert Jan Schrijver
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfRTS corp
 
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive ReviewRevolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Reviewjw364beach
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...kalichargn70th171
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxRTS corp
 
Business Analyzopedia - Your Pocket Gita for Business Analysis
Business Analyzopedia - Your Pocket Gita for Business AnalysisBusiness Analyzopedia - Your Pocket Gita for Business Analysis
Business Analyzopedia - Your Pocket Gita for Business AnalysisDEEPRAJ PATHAK
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsJean Silva
 
logical backup of Oracle Datapump-detailed.pptx
logical backup of Oracle Datapump-detailed.pptxlogical backup of Oracle Datapump-detailed.pptx
logical backup of Oracle Datapump-detailed.pptxRemote DBA Services
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorTier1 app
 
What is Mendix and the concept of low-code development.docx
What is Mendix and the concept of low-code development.docxWhat is Mendix and the concept of low-code development.docx
What is Mendix and the concept of low-code development.docxTechnogeeks
 
full course of software engineering mid term.pdf
full course of software engineering mid term.pdffull course of software engineering mid term.pdf
full course of software engineering mid term.pdfAbdul salam
 

Recently uploaded (20)

Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
Revolutionizing the Digital Transformation Office - Leveraging OnePlan’s AI a...
 
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptxUnderstanding Plagiarism: Causes, Consequences and Prevention.pptx
Understanding Plagiarism: Causes, Consequences and Prevention.pptx
 
eSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration toolseSoftTools IMAP Backup Software and migration tools
eSoftTools IMAP Backup Software and migration tools
 
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News UpdateVictoriaMetrics Q1 Meet Up '24 - Community & News Update
VictoriaMetrics Q1 Meet Up '24 - Community & News Update
 
Keeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository worldKeeping your build tool updated in a multi repository world
Keeping your build tool updated in a multi repository world
 
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdfPros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
Pros and Cons of Selenium In Automation Testing_ A Comprehensive Assessment.pdf
 
Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...
Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...
Transform your Corporate Strategy Office - Harness OnePlan’s Strategic Portfo...
 
SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?SAM Training Session - How to use EXCEL ?
SAM Training Session - How to use EXCEL ?
 
Osi security architecture in network.pptx
Osi security architecture in network.pptxOsi security architecture in network.pptx
Osi security architecture in network.pptx
 
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
JavaLand 2024 - Going serverless with Quarkus GraalVM native images and AWS L...
 
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdfEnhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
Enhancing Supply Chain Visibility with Cargo Cloud Solutions.pdf
 
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive ReviewRevolutionize Your Video Editing with InVideo.io: A Comprehensive Review
Revolutionize Your Video Editing with InVideo.io: A Comprehensive Review
 
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
The Ultimate Guide to Performance Testing in Low-Code, No-Code Environments (...
 
Advantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptxAdvantages of Cargo Cloud Solutions.pptx
Advantages of Cargo Cloud Solutions.pptx
 
Business Analyzopedia - Your Pocket Gita for Business Analysis
Business Analyzopedia - Your Pocket Gita for Business AnalysisBusiness Analyzopedia - Your Pocket Gita for Business Analysis
Business Analyzopedia - Your Pocket Gita for Business Analysis
 
Strategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero resultsStrategies for using alternative queries to mitigate zero results
Strategies for using alternative queries to mitigate zero results
 
logical backup of Oracle Datapump-detailed.pptx
logical backup of Oracle Datapump-detailed.pptxlogical backup of Oracle Datapump-detailed.pptx
logical backup of Oracle Datapump-detailed.pptx
 
Effectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryErrorEffectively Troubleshoot 9 Types of OutOfMemoryError
Effectively Troubleshoot 9 Types of OutOfMemoryError
 
What is Mendix and the concept of low-code development.docx
What is Mendix and the concept of low-code development.docxWhat is Mendix and the concept of low-code development.docx
What is Mendix and the concept of low-code development.docx
 
full course of software engineering mid term.pdf
full course of software engineering mid term.pdffull course of software engineering mid term.pdf
full course of software engineering mid term.pdf
 

Modern SQL in Open Source and Commercial Databases