SlideShare a Scribd company logo
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 (20)

database application using SQL DML statements: all types of Join, Sub-Query ...
 database application using SQL DML statements: all types of Join, Sub-Query ... database application using SQL DML statements: all types of Join, Sub-Query ...
database application using SQL DML statements: all types of Join, Sub-Query ...
bhavesh lande
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with Overview
Shahed Chowdhuri
 
Sql a practical introduction
Sql   a practical introductionSql   a practical introduction
Sql a practical introduction
Hasan Kata
 
Manipulation des Données , cours sql oracle
Manipulation des Données , cours sql oracleManipulation des Données , cours sql oracle
Manipulation des Données , cours sql oracle
webreaker
 
Java Programming for Designers
Java Programming for DesignersJava Programming for Designers
Java Programming for Designers
R. Sosa
 
Exception handling in plsql
Exception handling in plsqlException handling in plsql
Exception handling in plsql
Arun Sial
 
Dr. Rajeshree Khande :Introduction to Java AWT
Dr. Rajeshree Khande :Introduction to Java AWTDr. Rajeshree Khande :Introduction to Java AWT
Dr. Rajeshree Khande :Introduction to Java AWT
DrRajeshreeKhande
 
Advanced MySQL Query Tuning
Advanced MySQL Query TuningAdvanced MySQL Query Tuning
Advanced MySQL Query Tuning
Alexander Rubin
 
Sql query patterns, optimized
Sql query patterns, optimizedSql query patterns, optimized
Sql query patterns, optimized
Karwin Software Solutions LLC
 
Oracle Course
Oracle CourseOracle Course
Oracle Course
rspaike
 
MySQL Cheat Sheet
MySQL Cheat SheetMySQL Cheat Sheet
MySQL Cheat Sheet
Chen Dominique
 
Cracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 ExamsCracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 Exams
Ganesh Samarthyam
 
JCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTSJCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTS
Joseph Kuo
 
SQL
SQLSQL
SQL
Shunya Ram
 
Asp.net.
Asp.net.Asp.net.
Asp.net.
Naveen Sihag
 
Pl sql student guide v 1
Pl sql student guide v 1Pl sql student guide v 1
Pl sql student guide v 1
Nexus
 
React workshop
React workshopReact workshop
React workshop
Imran Sayed
 
[APJ] Common Table Expressions (CTEs) in SQL
[APJ] Common Table Expressions (CTEs) in SQL[APJ] Common Table Expressions (CTEs) in SQL
[APJ] Common Table Expressions (CTEs) in SQL
EDB
 
Особенности ETL — инструмента pentaho data integrator. Опыт КРОК
Особенности ETL — инструмента pentaho data integrator. Опыт КРОКОсобенности ETL — инструмента pentaho data integrator. Опыт КРОК
Особенности ETL — инструмента pentaho data integrator. Опыт КРОК
КРОК
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShell
Salaudeen Rajack
 
database application using SQL DML statements: all types of Join, Sub-Query ...
 database application using SQL DML statements: all types of Join, Sub-Query ... database application using SQL DML statements: all types of Join, Sub-Query ...
database application using SQL DML statements: all types of Join, Sub-Query ...
bhavesh lande
 
ASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with OverviewASP.NET Core MVC + Web API with Overview
ASP.NET Core MVC + Web API with Overview
Shahed Chowdhuri
 
Sql a practical introduction
Sql   a practical introductionSql   a practical introduction
Sql a practical introduction
Hasan Kata
 
Manipulation des Données , cours sql oracle
Manipulation des Données , cours sql oracleManipulation des Données , cours sql oracle
Manipulation des Données , cours sql oracle
webreaker
 
Java Programming for Designers
Java Programming for DesignersJava Programming for Designers
Java Programming for Designers
R. Sosa
 
Exception handling in plsql
Exception handling in plsqlException handling in plsql
Exception handling in plsql
Arun Sial
 
Dr. Rajeshree Khande :Introduction to Java AWT
Dr. Rajeshree Khande :Introduction to Java AWTDr. Rajeshree Khande :Introduction to Java AWT
Dr. Rajeshree Khande :Introduction to Java AWT
DrRajeshreeKhande
 
Advanced MySQL Query Tuning
Advanced MySQL Query TuningAdvanced MySQL Query Tuning
Advanced MySQL Query Tuning
Alexander Rubin
 
Oracle Course
Oracle CourseOracle Course
Oracle Course
rspaike
 
Cracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 ExamsCracking OCA and OCP Java 8 Exams
Cracking OCA and OCP Java 8 Exams
Ganesh Samarthyam
 
JCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTSJCConf 2021 - Java17: The Next LTS
JCConf 2021 - Java17: The Next LTS
Joseph Kuo
 
Pl sql student guide v 1
Pl sql student guide v 1Pl sql student guide v 1
Pl sql student guide v 1
Nexus
 
[APJ] Common Table Expressions (CTEs) in SQL
[APJ] Common Table Expressions (CTEs) in SQL[APJ] Common Table Expressions (CTEs) in SQL
[APJ] Common Table Expressions (CTEs) in SQL
EDB
 
Особенности ETL — инструмента pentaho data integrator. Опыт КРОК
Особенности ETL — инструмента pentaho data integrator. Опыт КРОКОсобенности ETL — инструмента pentaho data integrator. Опыт КРОК
Особенности ETL — инструмента pentaho data integrator. Опыт КРОК
КРОК
 
Introduction to PowerShell
Introduction to PowerShellIntroduction to PowerShell
Introduction to PowerShell
Salaudeen Rajack
 

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

Tech Jam 01 - Database Querying
Tech Jam 01 - Database QueryingTech Jam 01 - Database Querying
Tech Jam 01 - Database Querying
Rodger Oates
 
Modern sql
Modern sqlModern sql
Modern sql
Elizabeth Smith
 
PPT of Common Table Expression (CTE), Window Functions, JOINS, SubQuery
PPT  of Common Table Expression (CTE), Window Functions, JOINS, SubQueryPPT  of Common Table Expression (CTE), Window Functions, JOINS, SubQuery
PPT of Common Table Expression (CTE), Window Functions, JOINS, SubQuery
Abhishek590097
 
1. dml select statement reterive data
1. dml select statement reterive data1. dml select statement reterive data
1. dml select statement reterive data
Amrit Kaur
 
OracleSQLraining.pptx
OracleSQLraining.pptxOracleSQLraining.pptx
OracleSQLraining.pptx
Rajendra Jain
 
Common Table Expressions (CTE) & Window Functions in MySQL 8.0
Common Table Expressions (CTE) & Window Functions in MySQL 8.0Common Table Expressions (CTE) & Window Functions in MySQL 8.0
Common Table Expressions (CTE) & Window Functions in MySQL 8.0
oysteing
 
Intro to t sql – 3rd session
Intro to t sql – 3rd sessionIntro to t sql – 3rd session
Intro to t sql – 3rd session
Medhat Dawoud
 
Ctes percona live_2017
Ctes percona live_2017Ctes percona live_2017
Ctes percona live_2017
Guilhem Bichot
 
MySQL Optimizer: What’s New in 8.0
MySQL Optimizer: What’s New in 8.0MySQL Optimizer: What’s New in 8.0
MySQL Optimizer: What’s New in 8.0
oysteing
 
SQLSERVERQUERIES.pptx
SQLSERVERQUERIES.pptxSQLSERVERQUERIES.pptx
SQLSERVERQUERIES.pptx
ssuser6bf2d1
 
More Complex SQL and Concurrency ControlModule 4.pptx
More Complex SQL and Concurrency ControlModule 4.pptxMore Complex SQL and Concurrency ControlModule 4.pptx
More Complex SQL and Concurrency ControlModule 4.pptx
bgscseise
 
Sql analytic queries tips
Sql analytic queries tipsSql analytic queries tips
Sql analytic queries tips
Vedran Bilopavlović
 
Module 3.1.pptx
Module 3.1.pptxModule 3.1.pptx
Module 3.1.pptx
ANSHVAJPAI
 
MySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table Expressions MySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table Expressions
oysteing
 
MySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table ExpressionsMySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table Expressions
oysteing
 
Oracle Database Advanced Querying (2016)
Oracle Database Advanced Querying (2016)Oracle Database Advanced Querying (2016)
Oracle Database Advanced Querying (2016)
Zohar Elkayam
 
Subqueries, Backups, Users and Privileges
Subqueries, Backups, Users and PrivilegesSubqueries, Backups, Users and Privileges
Subqueries, Backups, Users and Privileges
Ashwin Dinoriya
 
SQLQueries
SQLQueriesSQLQueries
SQLQueries
karunakar81987
 
Database Management System - SQL Advanced Training
Database Management System - SQL Advanced TrainingDatabase Management System - SQL Advanced Training
Database Management System - SQL Advanced Training
Moutasm Tamimi
 
SQL Outer Joins for Fun and Profit
SQL Outer Joins for Fun and ProfitSQL Outer Joins for Fun and Profit
SQL Outer Joins for Fun and Profit
Karwin Software Solutions LLC
 
Tech Jam 01 - Database Querying
Tech Jam 01 - Database QueryingTech Jam 01 - Database Querying
Tech Jam 01 - Database Querying
Rodger Oates
 
PPT of Common Table Expression (CTE), Window Functions, JOINS, SubQuery
PPT  of Common Table Expression (CTE), Window Functions, JOINS, SubQueryPPT  of Common Table Expression (CTE), Window Functions, JOINS, SubQuery
PPT of Common Table Expression (CTE), Window Functions, JOINS, SubQuery
Abhishek590097
 
1. dml select statement reterive data
1. dml select statement reterive data1. dml select statement reterive data
1. dml select statement reterive data
Amrit Kaur
 
OracleSQLraining.pptx
OracleSQLraining.pptxOracleSQLraining.pptx
OracleSQLraining.pptx
Rajendra Jain
 
Common Table Expressions (CTE) & Window Functions in MySQL 8.0
Common Table Expressions (CTE) & Window Functions in MySQL 8.0Common Table Expressions (CTE) & Window Functions in MySQL 8.0
Common Table Expressions (CTE) & Window Functions in MySQL 8.0
oysteing
 
Intro to t sql – 3rd session
Intro to t sql – 3rd sessionIntro to t sql – 3rd session
Intro to t sql – 3rd session
Medhat Dawoud
 
Ctes percona live_2017
Ctes percona live_2017Ctes percona live_2017
Ctes percona live_2017
Guilhem Bichot
 
MySQL Optimizer: What’s New in 8.0
MySQL Optimizer: What’s New in 8.0MySQL Optimizer: What’s New in 8.0
MySQL Optimizer: What’s New in 8.0
oysteing
 
SQLSERVERQUERIES.pptx
SQLSERVERQUERIES.pptxSQLSERVERQUERIES.pptx
SQLSERVERQUERIES.pptx
ssuser6bf2d1
 
More Complex SQL and Concurrency ControlModule 4.pptx
More Complex SQL and Concurrency ControlModule 4.pptxMore Complex SQL and Concurrency ControlModule 4.pptx
More Complex SQL and Concurrency ControlModule 4.pptx
bgscseise
 
Module 3.1.pptx
Module 3.1.pptxModule 3.1.pptx
Module 3.1.pptx
ANSHVAJPAI
 
MySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table Expressions MySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table Expressions
oysteing
 
MySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table ExpressionsMySQL 8.0: Common Table Expressions
MySQL 8.0: Common Table Expressions
oysteing
 
Oracle Database Advanced Querying (2016)
Oracle Database Advanced Querying (2016)Oracle Database Advanced Querying (2016)
Oracle Database Advanced Querying (2016)
Zohar Elkayam
 
Subqueries, Backups, Users and Privileges
Subqueries, Backups, Users and PrivilegesSubqueries, Backups, Users and Privileges
Subqueries, Backups, Users and Privileges
Ashwin Dinoriya
 
Database Management System - SQL Advanced Training
Database Management System - SQL Advanced TrainingDatabase Management System - SQL Advanced Training
Database Management System - SQL Advanced Training
Moutasm Tamimi
 
Ad

More from Markus Winand (8)

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
Markus 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 Review
Markus 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 work
Markus 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 stack
Markus 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 20131202
Markus Winand
 
Indexes: The neglected performance all rounder
Indexes: The neglected performance all rounderIndexes: The neglected performance all rounder
Indexes: The neglected performance all rounder
Markus Winand
 
Pagination Done the Right Way
Pagination Done the Right WayPagination Done the Right Way
Pagination Done the Right Way
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 competitors
Markus 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 Review
Markus 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 work
Markus 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 stack
Markus 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 20131202
Markus Winand
 
Indexes: The neglected performance all rounder
Indexes: The neglected performance all rounderIndexes: The neglected performance all rounder
Indexes: The neglected performance all rounder
Markus Winand
 
Pagination Done the Right Way
Pagination Done the Right WayPagination Done the Right Way
Pagination Done the Right Way
Markus Winand
 
Ad

Recently uploaded (20)

Delivering More with Less: AI Driven Resource Management with OnePlan
Delivering More with Less: AI Driven Resource Management with OnePlan Delivering More with Less: AI Driven Resource Management with OnePlan
Delivering More with Less: AI Driven Resource Management with OnePlan
OnePlan Solutions
 
AI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATION
AI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATIONAI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATION
AI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATION
miso_uam
 
grade 9 ai project cycle Artificial intelligence.pptx
grade 9 ai project cycle Artificial intelligence.pptxgrade 9 ai project cycle Artificial intelligence.pptx
grade 9 ai project cycle Artificial intelligence.pptx
manikumar465287
 
Salesforce Experience Cloud Consulting.pdf
Salesforce Experience Cloud Consulting.pdfSalesforce Experience Cloud Consulting.pdf
Salesforce Experience Cloud Consulting.pdf
VALiNTRY360
 
Custom Software Development: Types, Applications and Benefits.pdf
Custom Software Development: Types, Applications and Benefits.pdfCustom Software Development: Types, Applications and Benefits.pdf
Custom Software Development: Types, Applications and Benefits.pdf
Digital Aptech
 
Climate-Smart Agriculture Development Solution.pptx
Climate-Smart Agriculture Development Solution.pptxClimate-Smart Agriculture Development Solution.pptx
Climate-Smart Agriculture Development Solution.pptx
julia smits
 
Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...
Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...
Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...
officeiqai
 
Secure and Simplify IT Management with ManageEngine Endpoint Central.pdf
Secure and Simplify IT Management with ManageEngine Endpoint Central.pdfSecure and Simplify IT Management with ManageEngine Endpoint Central.pdf
Secure and Simplify IT Management with ManageEngine Endpoint Central.pdf
Northwind Technologies
 
BoxLang-Dynamic-AWS-Lambda by Luis Majano.pdf
BoxLang-Dynamic-AWS-Lambda by Luis Majano.pdfBoxLang-Dynamic-AWS-Lambda by Luis Majano.pdf
BoxLang-Dynamic-AWS-Lambda by Luis Majano.pdf
Ortus Solutions, Corp
 
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
Philip Schwarz
 
Shortcomings of EHS Software – And How to Overcome Them
Shortcomings of EHS Software – And How to Overcome ThemShortcomings of EHS Software – And How to Overcome Them
Shortcomings of EHS Software – And How to Overcome Them
TECH EHS Solution
 
German Marketo User Group - May 2025 survey results
German Marketo User Group - May 2025 survey resultsGerman Marketo User Group - May 2025 survey results
German Marketo User Group - May 2025 survey results
BradBedford3
 
How a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdf
How a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdfHow a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdf
How a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdf
mary rojas
 
wAIred_LearnWithOutAI_LunchAndLearn_27052025.pptx
wAIred_LearnWithOutAI_LunchAndLearn_27052025.pptxwAIred_LearnWithOutAI_LunchAndLearn_27052025.pptx
wAIred_LearnWithOutAI_LunchAndLearn_27052025.pptx
SimonedeGijt
 
UberEats clone app Development TechBuilder
UberEats clone app Development  TechBuilderUberEats clone app Development  TechBuilder
UberEats clone app Development TechBuilder
TechBuilder
 
How to Recover Hacked Gmail Account || Help Email Tales
How to Recover Hacked Gmail Account || Help Email TalesHow to Recover Hacked Gmail Account || Help Email Tales
How to Recover Hacked Gmail Account || Help Email Tales
Roger Reed
 
Techdebt handling with cleancode focus and as risk taker
Techdebt handling with cleancode focus and as risk takerTechdebt handling with cleancode focus and as risk taker
Techdebt handling with cleancode focus and as risk taker
RajaNagendraKumar
 
VFP-Report-Copy-Data-Environment details
VFP-Report-Copy-Data-Environment detailsVFP-Report-Copy-Data-Environment details
VFP-Report-Copy-Data-Environment details
manojbkalla
 
Marketing And Sales Software Services.pptx
Marketing And Sales Software Services.pptxMarketing And Sales Software Services.pptx
Marketing And Sales Software Services.pptx
julia smits
 
Software Risk and Quality management.pptx
Software Risk and Quality management.pptxSoftware Risk and Quality management.pptx
Software Risk and Quality management.pptx
HassanBangash9
 
Delivering More with Less: AI Driven Resource Management with OnePlan
Delivering More with Less: AI Driven Resource Management with OnePlan Delivering More with Less: AI Driven Resource Management with OnePlan
Delivering More with Less: AI Driven Resource Management with OnePlan
OnePlan Solutions
 
AI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATION
AI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATIONAI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATION
AI-ASSISTED METAMORPHIC TESTING FOR DOMAIN-SPECIFIC MODELLING AND SIMULATION
miso_uam
 
grade 9 ai project cycle Artificial intelligence.pptx
grade 9 ai project cycle Artificial intelligence.pptxgrade 9 ai project cycle Artificial intelligence.pptx
grade 9 ai project cycle Artificial intelligence.pptx
manikumar465287
 
Salesforce Experience Cloud Consulting.pdf
Salesforce Experience Cloud Consulting.pdfSalesforce Experience Cloud Consulting.pdf
Salesforce Experience Cloud Consulting.pdf
VALiNTRY360
 
Custom Software Development: Types, Applications and Benefits.pdf
Custom Software Development: Types, Applications and Benefits.pdfCustom Software Development: Types, Applications and Benefits.pdf
Custom Software Development: Types, Applications and Benefits.pdf
Digital Aptech
 
Climate-Smart Agriculture Development Solution.pptx
Climate-Smart Agriculture Development Solution.pptxClimate-Smart Agriculture Development Solution.pptx
Climate-Smart Agriculture Development Solution.pptx
julia smits
 
Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...
Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...
Feeling Lost in the Blue? Exploring a New Path: AI Mental Health Counselling ...
officeiqai
 
Secure and Simplify IT Management with ManageEngine Endpoint Central.pdf
Secure and Simplify IT Management with ManageEngine Endpoint Central.pdfSecure and Simplify IT Management with ManageEngine Endpoint Central.pdf
Secure and Simplify IT Management with ManageEngine Endpoint Central.pdf
Northwind Technologies
 
BoxLang-Dynamic-AWS-Lambda by Luis Majano.pdf
BoxLang-Dynamic-AWS-Lambda by Luis Majano.pdfBoxLang-Dynamic-AWS-Lambda by Luis Majano.pdf
BoxLang-Dynamic-AWS-Lambda by Luis Majano.pdf
Ortus Solutions, Corp
 
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
List Unfolding - 'unfold' as the Computational Dual of 'fold', and how 'unfol...
Philip Schwarz
 
Shortcomings of EHS Software – And How to Overcome Them
Shortcomings of EHS Software – And How to Overcome ThemShortcomings of EHS Software – And How to Overcome Them
Shortcomings of EHS Software – And How to Overcome Them
TECH EHS Solution
 
German Marketo User Group - May 2025 survey results
German Marketo User Group - May 2025 survey resultsGerman Marketo User Group - May 2025 survey results
German Marketo User Group - May 2025 survey results
BradBedford3
 
How a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdf
How a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdfHow a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdf
How a Staff Augmentation Company IN USA Powers Flutter App Breakthroughs.pdf
mary rojas
 
wAIred_LearnWithOutAI_LunchAndLearn_27052025.pptx
wAIred_LearnWithOutAI_LunchAndLearn_27052025.pptxwAIred_LearnWithOutAI_LunchAndLearn_27052025.pptx
wAIred_LearnWithOutAI_LunchAndLearn_27052025.pptx
SimonedeGijt
 
UberEats clone app Development TechBuilder
UberEats clone app Development  TechBuilderUberEats clone app Development  TechBuilder
UberEats clone app Development TechBuilder
TechBuilder
 
How to Recover Hacked Gmail Account || Help Email Tales
How to Recover Hacked Gmail Account || Help Email TalesHow to Recover Hacked Gmail Account || Help Email Tales
How to Recover Hacked Gmail Account || Help Email Tales
Roger Reed
 
Techdebt handling with cleancode focus and as risk taker
Techdebt handling with cleancode focus and as risk takerTechdebt handling with cleancode focus and as risk taker
Techdebt handling with cleancode focus and as risk taker
RajaNagendraKumar
 
VFP-Report-Copy-Data-Environment details
VFP-Report-Copy-Data-Environment detailsVFP-Report-Copy-Data-Environment details
VFP-Report-Copy-Data-Environment details
manojbkalla
 
Marketing And Sales Software Services.pptx
Marketing And Sales Software Services.pptxMarketing And Sales Software Services.pptx
Marketing And Sales Software Services.pptx
julia smits
 
Software Risk and Quality management.pptx
Software Risk and Quality management.pptxSoftware Risk and Quality management.pptx
Software Risk and Quality management.pptx
HassanBangash9
 

Modern SQL in Open Source and Commercial Databases