SlideShare a Scribd company logo
1 of 124
Download to read offline
@vlad_mihalcea vladmihalcea.com
Awesome
SQL
Tips and Tricks
@vlad_mihalcea vladmihalcea.com
About me
• Java Champion
• vladmihalcea.com
• @vlad_mihalcea
• vladmihalcea
@vlad_mihalcea vladmihalcea.com
InfoQ – Trends Report
https://www.infoq.com/articles/architecture-trends-2019/
@vlad_mihalcea vladmihalcea.com
InfoQ – Trends Report
https://www.infoq.com/articles/architecture-trends-2019/
@vlad_mihalcea vladmihalcea.com
StackOverflow Survey – Most Popular Technologies
https://insights.stackoverflow.com/survey/2019
@vlad_mihalcea vladmihalcea.com
SQL is old school
https://www.pexels.com/photo/antique-blur-classic-close-up-595699/
@vlad_mihalcea vladmihalcea.com
SQL – ‘70s
1970
E.F. Codd’s from IBM
Relational Model
1974
D. D. Chamberlin & R. F. Boyce
IBM System R
1974
Michael Stonebraker
Berkeley Ingres
1979
Relational Software, Inc.
Oracle V2 Marketing
@vlad_mihalcea vladmihalcea.com
SQL – ‘80s
IBM System R
1981
IBM SQL/DS 1983
IBM DB2
1987
IBM DB2 for OS/2
1985
Robert Epstein
Sybase
Berkeley Ingres
1988
Microsoft
Sybase SQL Server
1985
Michael Stonebraker
POSTGRES
@vlad_mihalcea vladmihalcea.com
SQL – ‘90s
1995
David Axmark & Michael Widenius
MySQL
Sybase SQL Server
1993
Microsoft
SQL Server
POSTGRES
1996
PostgreSQL
@vlad_mihalcea vladmihalcea.com
Why is SQL still used?
https://qr.ae/TWCBD5
@vlad_mihalcea vladmihalcea.com
StackOverflow Survey – Most Popular Databases
https://insights.stackoverflow.com/survey/2019
@vlad_mihalcea vladmihalcea.com
StackOverflow Survey – Most Popular Databases
https://insights.stackoverflow.com/survey/2019
@vlad_mihalcea vladmihalcea.com
What does SQL stand for?
S? Query Language
@vlad_mihalcea vladmihalcea.com
What does SQL stand for?
https://twitter.com/vlad_mihalcea/status/1172446336131596289
@vlad_mihalcea vladmihalcea.com
SQL Standard
Photo by Frederick Tubiermont on Unsplash https://unsplash.com/photos/fJSRg-r7LuI
@vlad_mihalcea vladmihalcea.com
SQL:92
@vlad_mihalcea vladmihalcea.com
SQL:92
• In 1992, a major version of the standard was released. The
specification grew from 115 pages to 580.
• SQL:92 adds support for:
• DATE, TIME, TIMESTAMP, INTERVAL, BIT, VARCHAR, NVARCHAR,
• UNION, NATURAL JOIN,
• CASE expressions,
• CHECK constraints,
• Type casting (e.g., CAST (expr AS type))
@vlad_mihalcea vladmihalcea.com
SQL:92
• Other SQL:92 features include:
• INFORMATION_SCHEMA,
• Dynamic query execution (e.g., java.sql.Statement). Previously, only
prepared statements were supported.
• Temporary tables,
• Custom isolation levels,
• Database cursors,
• Scalar operations like String concatenation, date manipulation.
@vlad_mihalcea vladmihalcea.com
Fetching one-to-many relationship with pagination
@vlad_mihalcea vladmihalcea.com
Fetching one-to-many relationship with pagination
We need to get the first 2 post entries
starting with a given string value, along
with all their associated post_comment
child records.
@vlad_mihalcea vladmihalcea.com
post
id review post_id
1 SQL:2016 is great! 1
2 SQL:2016 is excellent! 1
3
SQL:20016 is awesome!
1
4 SQL:2011 is great! 2
5 SQL:2011 is excellent! 2
7 SQL:2008 is great! 3
id title
1 SQL:2016
2 SQL:2011
3 SQL:2008
Fetching one-to-many relationship with pagination
post_comment
post_id post_title comment_id comment_review
1 SQL:2016 1 SQL:2016 is great!
1 SQL:2016 2 SQL:2016 is excellent!
1 SQL:2016 3
SQL:20016 is awesome!
Result set
@vlad_mihalcea vladmihalcea.com
post
id review post_id
1 SQL:2016 is great! 1
2 SQL:2016 is excellent! 1
3
SQL:20016 is awesome!
1
4 SQL:2011 is great! 2
5 SQL:2011 is excellent! 2
7 SQL:2008 is great! 3
id title
1 SQL:2016
2 SQL:2011
3 SQL:2008
Fetching one-to-many relationship with pagination
post_comment
post_id post_title comment_id comment_review
1 SQL:2016 1 SQL:2016 is great!
1 SQL:2016 2 SQL:2016 is excellent!
1 SQL:2016 3
SQL:20016 is awesome!
2 SQL:2011 4 SQL:2011 is great!
2 SQL:2011 5 SQL:2011 is excellent!
Result set
@vlad_mihalcea vladmihalcea.com
JPQL – Join fetch with Pagination
List<Post> posts = entityManager
.createQuery(
"""
select p
from Post p
left join fetch p.comments pc
where p.title like :title
order by p.id, pc.id
""", Post.class)
.setParameter("title", "SQL%")
.setMaxResults(2)
.getResultList();
@vlad_mihalcea vladmihalcea.com
JPQL – Join fetch with Pagination
WARN [main]: QueryTranslatorImpl - HHH000104:
firstResult/maxResults specified with collection fetch;
applying in memory!
SELECT
p.id AS id1_0_0_,
p.title AS title3_0_0_,
pc.id AS id1_1_0__,
pc.post_id AS post_id4_1_1_,
pc.review AS review3_1_1_
FROM post p
LEFT OUTER JOIN post_comment pc ON p.id = pc.post_id
WHERE p.title LIKE 'SQL%'
ORDER BY p.id, pc.id
@vlad_mihalcea vladmihalcea.com
SQL – Join fetch with Pagination
SELECT
p.id AS post_id,
p.title AS post_title,
pc.id AS comment_id,
pc.review AS comment_review
FROM post p
LEFT JOIN post_comment pc ON p.id = pc.post_id
WHERE p.id IN (
SELECT id
FROM post
WHERE p.title LIKE 'SQL%'
ORDER BY id
LIMIT 2
)
ORDER BY post_id, comment_id
@vlad_mihalcea vladmihalcea.com
SQL – Derived tables – Oracle Top N
SELECT t.*
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t
WHERE ROWNUM <= 5
ORDER BY ROWNUM
We must sort the result set prior to assigning the
row ranking numbers.
@vlad_mihalcea vladmihalcea.com
SQL – Derived tables – Oracle Top N
SELECT t.*
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t
WHERE ROWNUM <= 5
ORDER BY ROWNUM
The outer query can now limit the result set size.
@vlad_mihalcea vladmihalcea.com
SQL – Derived tables – Oracle Next N
SELECT t2.*
FROM (
SELECT t1.*, ROWNUM AS ROW_NUM
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t1
WHERE ROWNUM <= 10
) t2
WHERE ROW_NUM > 5
ORDER BY ROW_NUM
We must sort the result set prior to assigning the
row ranking numbers.
@vlad_mihalcea vladmihalcea.com
SQL – Derived tables – Oracle Next N
SELECT t2.*
FROM (
SELECT t1.*, ROWNUM AS ROW_NUM
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t1
WHERE ROWNUM <= 10
) t2
WHERE ROW_NUM > 5
ORDER BY ROW_NUM
The following outer query can now limit the result
set size.
@vlad_mihalcea vladmihalcea.com
SQL – Derived tables – Oracle Next N
SELECT t2.*
FROM (
SELECT t1.*, ROWNUM AS ROW_NUM
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t1
WHERE ROWNUM <= 10
) t2
WHERE ROW_NUM > 5
ORDER BY ROW_NUM
The outer-most query can set the offset where we
want to start streaming the result set back to the
DB client.
@vlad_mihalcea vladmihalcea.com
SQL:92
@vlad_mihalcea vladmihalcea.com
SQL Standard timeline
SQL:86 SQL:89 SQL:92
@vlad_mihalcea vladmihalcea.com
SQL Standard timeline
SQL:86 SQL:89 SQL:92 SQL:1999
SQL:2011 SQL:2008 SQL:2006 SQL:2003
SQL:2016
@vlad_mihalcea vladmihalcea.com
SQL:1999
• In 1999, a new major version of the standard was released.
• It added support for:
• Boolean column type,
• WITH CTE (Common Table Expression) queries and WITH RECURSIVE queries
for hierarchic queries,
• ROLLUP, CUBE, GROUPING SETS for GROUP BY,
• Initial support for ARRAY types (e.g., UNNEST)
@vlad_mihalcea vladmihalcea.com
Pyramid of Doom
SELECT t2.*
FROM (
SELECT t1.*, ROWNUM AS ROW_NUM
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t1
WHERE ROWNUM <= 10
) t2
WHERE ROW_NUM > 5
ORDER BY ROW_NUM
@vlad_mihalcea vladmihalcea.com
• Supported databases:
• Oracle 9i R2
• SQL Server 2005
• PostgreSQL 8.4
• MySQL 8.0.1
• MariaDB 10.2.1
CTE (Common Table Expression)
@vlad_mihalcea vladmihalcea.com
SQL – CTE
WITH
p AS (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
),
p_limit AS (
SELECT p.*, ROWNUM AS ROW_NUM
FROM p
WHERE ROWNUM <= 10
)
SELECT title
FROM p_limit
WHERE ROW_NUM > 5
ORDER BY ROWNUM
@vlad_mihalcea vladmihalcea.com
SQL – CTE
WITH
p AS (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
),
p_limit AS (
SELECT p.*, ROWNUM AS ROW_NUM
FROM p
WHERE ROWNUM <= 10
)
SELECT title
FROM p_limit
WHERE ROW_NUM > 5
ORDER BY ROWNUM
@vlad_mihalcea vladmihalcea.com
SQL – CTE
WITH
p AS (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
),
p_limit AS (
SELECT p.*, ROWNUM AS ROW_NUM
FROM p
WHERE ROWNUM <= 10
)
SELECT title
FROM p_limit
WHERE ROW_NUM > 5
ORDER BY ROWNUM
@vlad_mihalcea vladmihalcea.com
Fetching hierarchical data
6 + 2 + 2 + 1 + …
total_score
@vlad_mihalcea vladmihalcea.com
Fetching hierarchical data
@vlad_mihalcea vladmihalcea.com
Fetch the top 3 comment hierarchies by total score
We need to get the top 3 post_comment
hierarchies based on their total
post_comment score.
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – table records
post_comment
4 = 1 + 2 + 2 + 1
total_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – table records
post_comment
3 = 1 + 1 + 1
total_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – table records
post_comment
9 = 1 + 10 - 2
total_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – table records
post_comment
-5
total_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – table records
post_comment
0
total_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching all data – application-level sorting
SELECT
id,
parent_id,
review,
created_on,
score
FROM post_comment
WHERE
post_id = 1
post_comment
@vlad_mihalcea vladmihalcea.com
Fetching all data – application-level sorting
Map<Long, PostCommentScore> postCommentScoreMap = postCommentScores
.stream()
.collect(Collectors.toMap(PostCommentScore::getId, Function.identity()));
List<PostCommentScore> postCommentRoots = postCommentScores
.stream()
.filter(pcs -> {
boolean isRoot = pcs.getParentId() == null;
if(!isRoot) {
postCommentScoreMap.get(pcs.getParentId()).addChild(pcs);
}
return isRoot;
})
.sorted(
Comparator.comparing(PostCommentScore::getTotalScore).reversed()
)
.limit(ranking)
.collect(Collectors.toList());
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – 1st level
SELECT
id,
parent_id,
review,
created_on,
score
FROM post_comment
WHERE
post_id = 1 AND
parent_id IS NULL
Fetch all root-level comments.
post_comment
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – 2nd level
WITH pc_r AS (
SELECT
id, parent_id, review,
created_on, score
FROM post_comment
WHERE
post_id = 1 AND
parent_id IS NULL
)
SELECT *
FROM pc_r
UNION ALL
SELECT
pc.id, pc.parent_id,
pc.review, pc.created_on,
pc.score
FROM post_comment pc
INNER JOIN pc_r
ON pc_r.id = pc.parent_id
post_comment
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
Fetching hierarchical data – 2nd level
WITH pc_r AS (
SELECT
id, parent_id, review,
created_on, score
FROM post_comment
WHERE
post_id = 1 AND
parent_id IS NULL
)
SELECT *
FROM pc_r
UNION ALL
SELECT
pc.id, pc.parent_id,
pc.review, pc.created_on,
pc.score
FROM post_comment pc
INNER JOIN pc_r
ON pc_r.id = pc.parent_id
post_comment
@vlad_mihalcea vladmihalcea.com
Fetching hierarchical data – Nth level
This approach of merging manually (using
UNION ALL) the result sets of each
individual level is cumbersome and requires
us knowing the number of levels upfront.
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
)
The result set table built recursively
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
)
We want to propagate the root_id
to all comments belonging to the
same hierarchy.
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
SELECT
id, id, post_id, parent_id, review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
)
Anchor member – the 1st level
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
SELECT
id, id, post_id, parent_id, review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
)
Anchor member – the 1st level
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
SELECT
id, id, post_id, parent_id, review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id
)
Recursive member – the 2nd to Nth level
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
SELECT
id, id, post_id, parent_id, review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id
)
Joining the current and previous levels
@vlad_mihalcea vladmihalcea.com
SQL – Recursive CTE
WITH RECURSIVE
post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS (
SELECT
id, id, post_id, parent_id, review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id, review, created_on, score
FROM post_comment_score
Result set projection query
@vlad_mihalcea vladmihalcea.com
Recursive CTE – 1st level
WITH RECURSIVE post_comment_score(
id, root_id, post_id, parent_id,
review, created_on, score)
AS (
SELECT
id, id, post_id, parent_id,
review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id,
pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs
ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id,
review, created_on, score
FROM post_comment_score
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
post_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
Recursive CTE – 1st level
WITH RECURSIVE post_comment_score(
id, root_id, post_id, parent_id,
review, created_on, score)
AS (
SELECT
id, id, post_id, parent_id,
review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id,
pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs
ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id,
review, created_on, score
FROM post_comment_score
post_comment_score
@vlad_mihalcea vladmihalcea.com
Recursive CTE – 2nd level
WITH RECURSIVE post_comment_score(
id, root_id, post_id, parent_id,
review, created_on, score)
AS (
SELECT
id, id, post_id, parent_id,
review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id,
pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs
ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id,
review, created_on, score
FROM post_comment_score
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
post_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
Recursive CTE – 2nd level
WITH RECURSIVE post_comment_score(
id, root_id, post_id, parent_id,
review, created_on, score)
AS (
SELECT
id, id, post_id, parent_id,
review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id,
pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs
ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id,
review, created_on, score
FROM post_comment_score
post_comment_score
@vlad_mihalcea vladmihalcea.com
Recursive CTE – 3rd level
WITH RECURSIVE post_comment_score(
id, root_id, post_id, parent_id,
review, created_on, score)
AS (
SELECT
id, id, post_id, parent_id,
review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id,
pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs
ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id,
review, created_on, score
FROM post_comment_score
id parent_id review created_on score post_id
1 Comment 1 2019-10-13 12:23:05 1 1
2 1 Comment 1.1 2019-10-14 13:23:10 2 1
3 1 Comment 1.2 2019-10-14 15:45:15 2 1
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1
5 Comment 2 2019-10-13 15:23:25 1 1
6 5 Comment 2.1 2019-10-14 11:23:30 1 1
7 5 Comment 2.2 2019-10-14 14:45:35 1 1
8 Comment 3 2019-10-15 10:15:40 1 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 1
11 Comment 4 2019-10-19 21:43:55 -5 1
12 Comment 5 2019-10-22 23:45:00 0 1
post_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Recursive CTE – 3rd level
WITH RECURSIVE post_comment_score(
id, root_id, post_id, parent_id,
review, created_on, score)
AS (
SELECT
id, id, post_id, parent_id,
review, created_on, score
FROM post_comment
WHERE post_id = 1 AND parent_id IS NULL
UNION ALL
SELECT
pc.id, pcs.root_id, pc.post_id, pc.parent_id,
pc.review, pc.created_on, pc.score
FROM post_comment pc
INNER JOIN post_comment_score pcs
ON pc.parent_id = pcs.id
)
SELECT
id, parent_id, root_id,
review, created_on, score
FROM post_comment_score
post_comment_score
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Why use Recursive CTE? post_comment_score
@vlad_mihalcea vladmihalcea.com
Window Functions
Photo by Numendil on Unsplash https://unsplash.com/photos/sSKNdbv3qNg
@vlad_mihalcea vladmihalcea.com
SQL:2003
• SQL:2003 was a minor version of SQL:1999.
• It added support for:
• Window Functions,
• MERGE statement
• SEQUNCE generator and IDENTITY column type,
• XML column type
@vlad_mihalcea vladmihalcea.com
• Supported databases:
• Oracle 8i
• SQL Server 2005
• PostgreSQL 8.4
• MySQL 8.0.2
• MariaDB 10.2.0
Window Functions
@vlad_mihalcea vladmihalcea.com
Summing up comment scores by root_id
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Summing comment scores – 1st root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
post_comment_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score total_score
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 Comment 2.2 2019-10-14 14:45:35 1
5 Comment 2 2019-10-13 15:23:25 1
8 Comment 3 2019-10-15 10:15:40 1
9 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 Comment 3.2 2019-10-17 18:30:50 -2
11 Comment 4 2019-10-19 21:43:55 -5
12 Comment 5 2019-10-22 23:45:00 0
Summing comment scores – 1st root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
total_score_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Summing comment scores – 2nd root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
post_comment_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score total_score
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1
9 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 Comment 3.2 2019-10-17 18:30:50 -2
11 Comment 4 2019-10-19 21:43:55 -5
12 Comment 5 2019-10-22 23:45:00 0
Summing comment scores – 2nd root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
total_score_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Summing comment scores – 3rd root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
post_comment_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score total_score
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1 9
9 8 Comment 3.1 2019-10-16 11:15:45 10 9
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9
11 Comment 4 2019-10-19 21:43:55 -5
12 Comment 5 2019-10-22 23:45:00 0
Summing comment scores – 3rd root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
total_score_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Summing comment scores – 4th root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
post_comment_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score total_score
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1 9
9 8 Comment 3.1 2019-10-16 11:15:45 10 9
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0
Summing comment scores – 4th root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
total_score_comment
@vlad_mihalcea vladmihalcea.com
id parent_id root_id review created_on score
1 1 Comment 1 2019-10-13 12:23:05 1
5 5 Comment 2 2019-10-13 15:23:25 1
8 8 Comment 3 2019-10-15 10:15:40 1
11 11 Comment 4 2019-10-19 21:43:55 -5
12 12 Comment 5 2019-10-22 23:45:00 0
2 1 1 Comment 1.1 2019-10-14 13:23:10 2
3 1 1 Comment 1.2 2019-10-14 15:45:15 2
6 5 5 Comment 2.1 2019-10-14 11:23:30 1
7 5 5 Comment 2.2 2019-10-14 14:45:35 1
9 8 8 Comment 3.1 2019-10-16 11:15:45 10
10 8 8 Comment 3.2 2019-10-17 18:30:50 -2
4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1
Summing comment scores – 5th root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
post_comment_score
@vlad_mihalcea vladmihalcea.com
id parent_id review created_on score total_score
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1 9
9 8 Comment 3.1 2019-10-16 11:15:45 10 9
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0 0
Summing comment scores – 5th root
total_score_comment
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
SUM(score) OVER (
PARTITION BY root_id
) AS total_score
FROM post_comment_score
),
total_score_comment
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores – 1st rank
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
id parent_id review created_on score total_score
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1 9
9 8 Comment 3.1 2019-10-16 11:15:45 10 9
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0 0
total_score_comme
nt
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores – 1st rank
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
id parent_id review created_on score total_score ranking
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
1 Comment 1 2019-10-13 12:23:05 1 6
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1 9 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0 0
total_score_ranking
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores – 2nd rank
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
id parent_id review created_on score total_score ranking
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2
2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2
3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2
1 Comment 1 2019-10-13 12:23:05 1 6 2
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
5 Comment 2 2019-10-13 15:23:25 1 3
8 Comment 3 2019-10-15 10:15:40 1 9 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0 0
total_score_ranking
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores – 3rd rank
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
id parent_id review created_on score total_score ranking
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2
2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2
3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2
1 Comment 1 2019-10-13 12:23:05 1 6 2
6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3
5 Comment 2 2019-10-13 15:23:25 1 3 3
8 Comment 3 2019-10-15 10:15:40 1 9 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0 0
total_score_ranking
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores – 4th rank
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
id parent_id review created_on score total_score ranking
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2
2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2
3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2
1 Comment 1 2019-10-13 12:23:05 1 6 2
6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3
5 Comment 2 2019-10-13 15:23:25 1 3 3
8 Comment 3 2019-10-15 10:15:40 1 9 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1
11 Comment 4 2019-10-19 21:43:55 -5 -5
12 Comment 5 2019-10-22 23:45:00 0 0 4
total_score_ranking
@vlad_mihalcea vladmihalcea.com
Ranking comment total scores – 5th rank
total_score_ranking
AS (
SELECT
id,
parent_id,
review,
created_on,
score,
total_score,
DENSE_RANK() OVER (
ORDER BY total_score DESC
) ranking
FROM total_score_comment
),
id parent_id review created_on score total_score ranking
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2
2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2
3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2
1 Comment 1 2019-10-13 12:23:05 1 6 2
6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3
5 Comment 2 2019-10-13 15:23:25 1 3 3
8 Comment 3 2019-10-15 10:15:40 1 9 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1
11 Comment 4 2019-10-19 21:43:55 -5 -5 5
12 Comment 5 2019-10-22 23:45:00 0 0 4
total_score_ranking
@vlad_mihalcea vladmihalcea.com
Filtering by the comment total score
SELECT
id,
parent_id,
review,
created_on,
score,
total_score
FROM total_score_ranking
WHERE
ranking <= 3
ORDER BY
total_score DESC,
id ASC
@vlad_mihalcea vladmihalcea.com
Filtering by the comment total score
SELECT
id,
parent_id,
review,
created_on,
score,
total_score
FROM total_score_ranking
WHERE
ranking <= 3
ORDER BY
total_score DESC,
id ASC
id parent_id review created_on score total_score ranking
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2
2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2
3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2
1 Comment 1 2019-10-13 12:23:05 1 6 2
6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3
5 Comment 2 2019-10-13 15:23:25 1 3 3
8 Comment 3 2019-10-15 10:15:40 1 9 1
9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1
11 Comment 4 2019-10-19 21:43:55 -5 -5 5
12 Comment 5 2019-10-22 23:45:00 0 0 4
total_score_ranking
@vlad_mihalcea vladmihalcea.com
Filtering by the comment total score
SELECT
id,
parent_id,
review,
created_on,
score,
total_score
FROM total_score_ranking
WHERE
ranking <= 3
ORDER BY
total_score DESC,
id ASC
id parent_id review created_on score total_score
8 Comment 3 2019-10-15 10:15:40 1 9
9 8 Comment 3.1 2019-10-16 11:15:45 10 9
10 8 Comment 3.2 2019-10-17 18:30:50 -2 9
1 Comment 1 2019-10-13 12:23:05 1 6
2 1 Comment 1.1 2019-10-14 13:23:10 2 6
3 1 Comment 1.2 2019-10-14 15:45:15 2 6
4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6
5 Comment 2 2019-10-13 15:23:25 1 3
6 5 Comment 2.1 2019-10-14 11:23:30 1 3
7 5 Comment 2.2 2019-10-14 14:45:35 1 3
Result set
@vlad_mihalcea vladmihalcea.com
Application-level vs database processing
20 104 656 2040 4640 15024 34880
0
10
20
30
40
50
60
70
80
90
100
Data set size
Time(ms)
Application-level Recursive CTE
@vlad_mihalcea vladmihalcea.com
SQL:2003
• SQL:2003 was a minor version of SQL:1999.
• It added support for:
• Window Functions,
• MERGE statement
• SEQUNCE generator and IDENTITY column type,
• XML column type
@vlad_mihalcea vladmihalcea.com
• Supported databases:
• Oracle 9i
• SQL Server 2008
• PostgreSQL and MySQL offer non-standard UPSERT alternatives.
MERGE
@vlad_mihalcea vladmihalcea.com
Oracle MERGE – Ignore on constraint violation
MERGE INTO book
USING (SELECT 1 FROM dual) ON (id = 1)
WHEN NOT MATCHED THEN
INSERT (
id,
title,
isbn
)
VALUES (
1,
'High-Performance Java Persistence',
'978-9730228236'
)
@vlad_mihalcea vladmihalcea.com
Oracle MERGE – UPDATE on constraint violation
MERGE INTO book
USING (SELECT 1 FROM dual) ON (id = 1)
WHEN MATCHED THEN
UPDATE SET
title = 'High-Performance Java Persistence, 2nd Edition',
isbn = '978-9730228236'
WHEN NOT MATCHED THEN
INSERT (
id,
title,
isbn
)
VALUES (
1,
'High-Performance Java Persistence',
'978-9730228236'
)
@vlad_mihalcea vladmihalcea.com
SQL:2006
• SQL:2006 added support for:
• XQuery,
• SQL/XML functions (e.g., XMLELEMENT)
@vlad_mihalcea vladmihalcea.com
SQL:2008
• SQL:2008 added support for:
• TRUNCATE TABLE,
• Multiple WHEN clauses in CASE expressions,
• INSTEAD OF database triggers (override INSERT, UPDATE, DELETE),
• XQuery regular expression/pattern matching,
• Derived column list to override a derived table column names,
• Standard pagination using:
• FETCH FIRST N ROWS ONLY
• OFFSET M ROWS
@vlad_mihalcea vladmihalcea.com
SQL – Oracle legacy Top N
SELECT t.*
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t
WHERE ROWNUM <= 5
ORDER BY ROWNUM
@vlad_mihalcea vladmihalcea.com
SQL – Standard Top N
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
FETCH FIRST 5 ROWS ONLY
@vlad_mihalcea vladmihalcea.com
SQL – Oracle legacy Next N
SELECT t2.*
FROM (
SELECT t1.*, ROWNUM AS ROW_NUM
FROM (
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
) t1
WHERE ROWNUM <= 10
) t2
WHERE ROW_NUM > 5
ORDER BY ROW_NUM
@vlad_mihalcea vladmihalcea.com
SQL – Standard Next N
SELECT title
FROM post
ORDER BY created_on DESC, id DESC
OFFSET 5 ROWS
FETCH NEXT 5 ROWS ONLY
@vlad_mihalcea vladmihalcea.com
SQL:2011
• SQL: 2011 added support for
• Temporal database,
• System-versioned tables
@vlad_mihalcea vladmihalcea.com
SQL:2016
• SQL: 2016 added support for:
• JSON,
• MATCH_RECOGNIZE (Row Pattern Recognition),
• LISTAGG (aggregate multiple values to a delimited string value),
• DECFLOAT column type (e.g., decimal floating arithmetic),
• Date and Time formatting (e.g., CAST(.. AS .. FORMAT ..),
EXTRACT(.. FROM <datetime>))
@vlad_mihalcea vladmihalcea.com
• Supported databases:
• Oracle 12c
• SQL Server 2016
• PostgreSQL 9.2
• MySQL 5.6
• PostgreSQL and MySQL offer non-standard alternatives.
JSON
@vlad_mihalcea vladmihalcea.com
MySQL – storing JSON
CREATE TABLE book (
id bigint NOT NULL PRIMARY KEY,
isbn VARCHAR(15),
properties JSON
)
@vlad_mihalcea vladmihalcea.com
MySQL – Get scalar attribute
SELECT
id,
CAST(
properties -> '$.price'
AS DECIMAL(4, 2)
) AS price
FROM book
WHERE
properties -> '$.title' = 'High-Performance Java Persistence'
Without casting to DECIMAL, the result will be
returned as a String.
@vlad_mihalcea vladmihalcea.com
MySQL – Get scalar attribute
id isbn properties
1 978-9730228236
{
"title":"High-Performance Java Persistence",
"author":"Vlad Mihalcea",
"publisher":"Amazon",
"price":44.99,
"reviews":[
…
]
}
book
SELECT
id,
CAST(
properties -> '$.price'
AS DECIMAL(4, 2)
) AS price
FROM book
WHERE
properties -> '$.title' =
'High-Performance Java Persistence'
id price
1 44.99 Result set
@vlad_mihalcea vladmihalcea.com
SELECT
id,
properties -> '$.reviews' AS reviews
FROM book
WHERE
isbn = '978-9730228236'
MySQL – Get JSON object
@vlad_mihalcea vladmihalcea.com
MySQL – Get JSON object
SELECT
id,
properties -> '$.reviews' AS reviews
FROM book
WHERE
isbn = '978-9730228236'
id isbn properties
1 978-9730228236
{
"title":"High-Performance Java Persistence",
"author":"Vlad Mihalcea",
"publisher":"Amazon",
"price":44.99,
"reviews":[
{
"reviewer":"Cristiano",
"review":"Excellent book to understand Java Persistence",
"date":"2017-11-14",
"rating":5
},
{
"reviewer":"T.W",
"review":"The best JPA ORM book out there",
"date":"2019-01-27",
"rating":5
},
{
"reviewer":"Shaikh",
"review":"The most informative book",
"date":"2016-12-24",
"rating":4
}
]
}
book
id reviews
1
[
{..},
{..},
{..}
] Result set
@vlad_mihalcea vladmihalcea.com
SELECT r.*
FROM
book,
JSON_TABLE(
properties,
'$.reviews[*]'
COLUMNS(
reviewer VARCHAR(4000) PATH '$.reviewer',
review VARCHAR(4000) PATH '$.review',
review_date DATETIME PATH '$.date’,
rating INT PATH '$.rating'
)
) AS r
WHERE isbn = '978-9730228236'
MySQL – JSON to SQL table
@vlad_mihalcea vladmihalcea.com
SELECT r.*
FROM
book, JSON_TABLE(
properties,
'$.reviews[*]'
COLUMNS(
reviewer VARCHAR(4000) PATH '$.reviewer',
review VARCHAR(4000) PATH '$.review',
review_date DATETIME PATH '$.date’,
rating INT PATH '$.rating'
)
) AS r
WHERE isbn = '978-9730228236'
MySQL – JSON to SQL table
"reviews":[
{
"reviewer":"Cristiano",
"review":"Excellent book to understand Java Persistence",
"date":"2017-11-14",
"rating":5
},
{
"reviewer":"T.W",
"review":"The best JPA ORM book out there",
"date":"2019-01-27",
"rating":5
},
{
"reviewer":"Shaikh",
"review":"The most informative book",
"date":"2016-12-24",
"rating":4
}
]
reviewer review review_date rating
book
@vlad_mihalcea vladmihalcea.com
SELECT r.*
FROM
book, JSON_TABLE(
properties,
'$.reviews[*]'
COLUMNS(
reviewer VARCHAR(4000) PATH '$.reviewer',
review VARCHAR(4000) PATH '$.review',
review_date DATETIME PATH '$.date’,
rating INT PATH '$.rating'
)
) AS r
WHERE isbn = '978-9730228236'
MySQL – JSON to SQL table
"reviews":[
{
"reviewer":"Cristiano",
"review":"Excellent book to understand Java Persistence",
"date":"2017-11-14",
"rating":5
},
{
"reviewer":"T.W",
"review":"The best JPA ORM book out there",
"date":"2019-01-27",
"rating":5
},
{
"reviewer":"Shaikh",
"review":"The most informative book",
"date":"2016-12-24",
"rating":4
}
]
reviewer review review_date rating
Cristiano
Excellent book to understand Java
Persistence
14-Nov-2017 5
book
@vlad_mihalcea vladmihalcea.com
SELECT r.*
FROM
book, JSON_TABLE(
properties,
'$.reviews[*]'
COLUMNS(
reviewer VARCHAR(4000) PATH '$.reviewer',
review VARCHAR(4000) PATH '$.review',
review_date DATETIME PATH '$.date’,
rating INT PATH '$.rating'
)
) AS r
WHERE isbn = '978-9730228236'
MySQL – JSON to SQL table
"reviews":[
{
"reviewer":"Cristiano",
"review":"Excellent book to understand Java Persistence",
"date":"2017-11-14",
"rating":5
},
{
"reviewer":"T.W",
"review":"The best JPA ORM book out there",
"date":"2019-01-27",
"rating":5
},
{
"reviewer":"Shaikh",
"review":"The most informative book",
"date":"2016-12-24",
"rating":4
}
]
reviewer review review_date rating
Cristiano
Excellent book to understand Java
Persistence
14-Nov-2017 5
T.W The best JPA ORM book out there 27-Jan-2019 5
book
@vlad_mihalcea vladmihalcea.com
SELECT r.*
FROM
book, JSON_TABLE(
properties,
'$.reviews[*]'
COLUMNS(
reviewer VARCHAR(4000) PATH '$.reviewer',
review VARCHAR(4000) PATH '$.review',
review_date DATETIME PATH '$.date’,
rating INT PATH '$.rating'
)
) AS r
WHERE isbn = '978-9730228236'
MySQL – JSON to SQL table
"reviews":[
{
"reviewer":"Cristiano",
"review":"Excellent book to understand Java Persistence",
"date":"2017-11-14",
"rating":5
},
{
"reviewer":"T.W",
"review":"The best JPA ORM book out there",
"date":"2019-01-27",
"rating":5
},
{
"reviewer":"Shaikh",
"review":"The most informative book",
"date":"2016-12-24",
"rating":4
}
]
reviewer review review_date rating
Cristiano
Excellent book to understand Java
Persistence
14-Nov-2017 5
T.W The best JPA ORM book out there 27-Jan-2019 5
Shaikh The most informative book 24-Dec-2016 4book
@vlad_mihalcea vladmihalcea.com
SQL timeline
SQL NoSQL NewSQL
1974 2009 2011
@vlad_mihalcea vladmihalcea.com
NewSQL
https://www.pexels.com/photo/architectural-design-architecture-blue-brazil-416998/
@vlad_mihalcea vladmihalcea.com
CockroachDB – SQL support
https://www.cockroachlabs.com/docs/v19.1/sql-statements.html
@vlad_mihalcea vladmihalcea.com
VoltDB – SQL support
https://www.voltdb.com/product/features-benefits/sql-database/
@vlad_mihalcea vladmihalcea.com
VoltDB – SQL support
https://www.voltdb.com/product/features-benefits/sql-database/
@vlad_mihalcea vladmihalcea.com
VoltDB – SQL support
https://www.voltdb.com/product/features-benefits/sql-database/
@vlad_mihalcea vladmihalcea.com
Google BigQuery – SQL support
https://cloud.google.com/bigquery/docs/release-notes#March_23_2016
@vlad_mihalcea vladmihalcea.com
Google Spanner – SQL support
https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46103.pdf
@vlad_mihalcea vladmihalcea.com
Thank you
• Twitter: @vlad_mihalcea
• Blog: https://vladmihalcea.com/
• Courses: https://vladmihalcea.com/courses/
• Training: https://vladmihalcea.com/trainings/
• Book: https://vladmihalcea.com/books/high-performance-java-persistence/

More Related Content

What's hot

What's hot (20)

Postgresql
PostgresqlPostgresql
Postgresql
 
Cloudera Impala Source Code Explanation and Analysis
Cloudera Impala Source Code Explanation and AnalysisCloudera Impala Source Code Explanation and Analysis
Cloudera Impala Source Code Explanation and Analysis
 
ADO.Net Improvements in .Net 2.0
ADO.Net Improvements in .Net 2.0ADO.Net Improvements in .Net 2.0
ADO.Net Improvements in .Net 2.0
 
Connect 2016-Move Your XPages Applications to the Fast Lane
Connect 2016-Move Your XPages Applications to the Fast LaneConnect 2016-Move Your XPages Applications to the Fast Lane
Connect 2016-Move Your XPages Applications to the Fast Lane
 
OTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should Know
OTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should KnowOTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should Know
OTN TOUR 2016 - DBA Commands and Concepts That Every Developer Should Know
 
In Defense Of Core Data
In Defense Of Core DataIn Defense Of Core Data
In Defense Of Core Data
 
MySQL 5.7 - What's new and How to upgrade
MySQL 5.7 - What's new and How to upgradeMySQL 5.7 - What's new and How to upgrade
MySQL 5.7 - What's new and How to upgrade
 
Marmagna desai
Marmagna desaiMarmagna desai
Marmagna desai
 
Cold Hard Cache
Cold Hard CacheCold Hard Cache
Cold Hard Cache
 
MariaDB Optimizer
MariaDB OptimizerMariaDB Optimizer
MariaDB Optimizer
 
Advanced MySQL Query Optimizations
Advanced MySQL Query OptimizationsAdvanced MySQL Query Optimizations
Advanced MySQL Query Optimizations
 
20151010 my sq-landjavav2a
20151010 my sq-landjavav2a20151010 my sq-landjavav2a
20151010 my sq-landjavav2a
 
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
Inexpensive Datamasking for MySQL with ProxySQL — Data Anonymization for Deve...
 
Dutch PHP Conference 2021 - MySQL Indexes and Histograms
Dutch PHP Conference 2021 - MySQL Indexes and HistogramsDutch PHP Conference 2021 - MySQL Indexes and Histograms
Dutch PHP Conference 2021 - MySQL Indexes and Histograms
 
Oracle Database Advanced Querying (2016)
Oracle Database Advanced Querying (2016)Oracle Database Advanced Querying (2016)
Oracle Database Advanced Querying (2016)
 
MySQL 8.0 New Features -- September 27th presentation for Open Source Summit
MySQL 8.0 New Features -- September 27th presentation for Open Source SummitMySQL 8.0 New Features -- September 27th presentation for Open Source Summit
MySQL 8.0 New Features -- September 27th presentation for Open Source Summit
 
OOW16 - Oracle Database 12c - The Best Oracle Database 12c New Features for D...
OOW16 - Oracle Database 12c - The Best Oracle Database 12c New Features for D...OOW16 - Oracle Database 12c - The Best Oracle Database 12c New Features for D...
OOW16 - Oracle Database 12c - The Best Oracle Database 12c New Features for D...
 
Oracle result cache highload 2017
Oracle result cache highload 2017Oracle result cache highload 2017
Oracle result cache highload 2017
 
Enhancements that will make your sql database roar sp1 edition sql bits 2017
Enhancements that will make your sql database roar sp1 edition sql bits 2017Enhancements that will make your sql database roar sp1 edition sql bits 2017
Enhancements that will make your sql database roar sp1 edition sql bits 2017
 
Row level security in enterprise applications
Row level security in enterprise applicationsRow level security in enterprise applications
Row level security in enterprise applications
 

Similar to Awesome SQL Tips and Tricks - Voxxed Days Cluj - 2019

Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
InSync2011
 

Similar to Awesome SQL Tips and Tricks - Voxxed Days Cluj - 2019 (20)

How to Implement Distributed Data Store
How to Implement Distributed Data Store How to Implement Distributed Data Store
How to Implement Distributed Data Store
 
Sql interview prep
Sql interview prepSql interview prep
Sql interview prep
 
Performance tuning
Performance tuningPerformance tuning
Performance tuning
 
When to NoSQL and when to know SQL
When to NoSQL and when to know SQLWhen to NoSQL and when to know SQL
When to NoSQL and when to know SQL
 
Recursive Query Throwdown
Recursive Query ThrowdownRecursive Query Throwdown
Recursive Query Throwdown
 
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
 
Oracle Database 12c New Features for Developers and DBAs - OTN TOUR LA 2015
Oracle Database 12c  New Features for Developers and DBAs - OTN TOUR LA 2015Oracle Database 12c  New Features for Developers and DBAs - OTN TOUR LA 2015
Oracle Database 12c New Features for Developers and DBAs - OTN TOUR LA 2015
 
Dan Hotka's Top 10 Oracle 12c New Features
Dan Hotka's Top 10 Oracle 12c New FeaturesDan Hotka's Top 10 Oracle 12c New Features
Dan Hotka's Top 10 Oracle 12c New Features
 
SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)SDPHP - Percona Toolkit (It's Basically Magic)
SDPHP - Percona Toolkit (It's Basically Magic)
 
Oracle Material.pdf
Oracle Material.pdfOracle Material.pdf
Oracle Material.pdf
 
SQL Tutorial for Marketers
SQL Tutorial for MarketersSQL Tutorial for Marketers
SQL Tutorial for Marketers
 
Migration from mysql to elasticsearch
Migration from mysql to elasticsearchMigration from mysql to elasticsearch
Migration from mysql to elasticsearch
 
SQL-RISC: New Directions in SQLi Prevention - RSA USA 2013
SQL-RISC: New Directions in SQLi Prevention - RSA USA 2013SQL-RISC: New Directions in SQLi Prevention - RSA USA 2013
SQL-RISC: New Directions in SQLi Prevention - RSA USA 2013
 
PostgreSQL - масштабирование в моде, Valentine Gogichashvili (Zalando SE)
PostgreSQL - масштабирование в моде, Valentine Gogichashvili (Zalando SE)PostgreSQL - масштабирование в моде, Valentine Gogichashvili (Zalando SE)
PostgreSQL - масштабирование в моде, Valentine Gogichashvili (Zalando SE)
 
Do You Have the Time
Do You Have the TimeDo You Have the Time
Do You Have the Time
 
Open Source 1010 and Quest InSync presentations March 30th, 2021 on MySQL Ind...
Open Source 1010 and Quest InSync presentations March 30th, 2021 on MySQL Ind...Open Source 1010 and Quest InSync presentations March 30th, 2021 on MySQL Ind...
Open Source 1010 and Quest InSync presentations March 30th, 2021 on MySQL Ind...
 
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
Database & Technology 2 _ Richard Foote _ 10 things you probably dont know ab...
 
Ten query tuning techniques every SQL Server programmer should know
Ten query tuning techniques every SQL Server programmer should knowTen query tuning techniques every SQL Server programmer should know
Ten query tuning techniques every SQL Server programmer should know
 
Sql 2016 - What's New
Sql 2016 - What's NewSql 2016 - What's New
Sql 2016 - What's New
 
SQL server 2016 New Features
SQL server 2016 New FeaturesSQL server 2016 New Features
SQL server 2016 New Features
 

Recently uploaded

👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...
👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...
👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...
karishmasinghjnh
 
Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
ZurliaSoop
 
Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...
Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...
Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...
amitlee9823
 
Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
amitlee9823
 
Abortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Doha Qatar (+966572737505 ! Get CytotecAbortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Riyadh +966572737505 get cytotec
 
Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...
only4webmaster01
 
➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men 🔝Dindigul🔝 Escor...
➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men  🔝Dindigul🔝   Escor...➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men  🔝Dindigul🔝   Escor...
➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men 🔝Dindigul🔝 Escor...
amitlee9823
 
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
amitlee9823
 
➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men 🔝Thrissur🔝 Escor...
➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men  🔝Thrissur🔝   Escor...➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men  🔝Thrissur🔝   Escor...
➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men 🔝Thrissur🔝 Escor...
amitlee9823
 
Abortion pills in Jeddah | +966572737505 | Get Cytotec
Abortion pills in Jeddah | +966572737505 | Get CytotecAbortion pills in Jeddah | +966572737505 | Get Cytotec
Abortion pills in Jeddah | +966572737505 | Get Cytotec
Abortion pills in Riyadh +966572737505 get cytotec
 
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
amitlee9823
 
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
amitlee9823
 
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts ServiceCall Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 

Recently uploaded (20)

Thane Call Girls 7091864438 Call Girls in Thane Escort service book now -
Thane Call Girls 7091864438 Call Girls in Thane Escort service book now -Thane Call Girls 7091864438 Call Girls in Thane Escort service book now -
Thane Call Girls 7091864438 Call Girls in Thane Escort service book now -
 
April 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's AnalysisApril 2024 - Crypto Market Report's Analysis
April 2024 - Crypto Market Report's Analysis
 
👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...
👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...
👉 Amritsar Call Girl 👉📞 6367187148 👉📞 Just📲 Call Ruhi Call Girl Phone No Amri...
 
Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
Jual Obat Aborsi Surabaya ( Asli No.1 ) 085657271886 Obat Penggugur Kandungan...
 
Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...
Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...
Escorts Service Kumaraswamy Layout ☎ 7737669865☎ Book Your One night Stand (B...
 
Detecting Credit Card Fraud: A Machine Learning Approach
Detecting Credit Card Fraud: A Machine Learning ApproachDetecting Credit Card Fraud: A Machine Learning Approach
Detecting Credit Card Fraud: A Machine Learning Approach
 
Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
Call Girls Bommasandra Just Call 👗 7737669865 👗 Top Class Call Girl Service B...
 
Abortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Doha Qatar (+966572737505 ! Get CytotecAbortion pills in Doha Qatar (+966572737505 ! Get Cytotec
Abortion pills in Doha Qatar (+966572737505 ! Get Cytotec
 
Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...
Call Girls Indiranagar Just Call 👗 9155563397 👗 Top Class Call Girl Service B...
 
➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men 🔝Dindigul🔝 Escor...
➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men  🔝Dindigul🔝   Escor...➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men  🔝Dindigul🔝   Escor...
➥🔝 7737669865 🔝▻ Dindigul Call-girls in Women Seeking Men 🔝Dindigul🔝 Escor...
 
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
Junnasandra Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore...
 
➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men 🔝Thrissur🔝 Escor...
➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men  🔝Thrissur🔝   Escor...➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men  🔝Thrissur🔝   Escor...
➥🔝 7737669865 🔝▻ Thrissur Call-girls in Women Seeking Men 🔝Thrissur🔝 Escor...
 
Abortion pills in Jeddah | +966572737505 | Get Cytotec
Abortion pills in Jeddah | +966572737505 | Get CytotecAbortion pills in Jeddah | +966572737505 | Get Cytotec
Abortion pills in Jeddah | +966572737505 | Get Cytotec
 
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort ServiceBDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
BDSM⚡Call Girls in Mandawali Delhi >༒8448380779 Escort Service
 
DATA SUMMIT 24 Building Real-Time Pipelines With FLaNK
DATA SUMMIT 24  Building Real-Time Pipelines With FLaNKDATA SUMMIT 24  Building Real-Time Pipelines With FLaNK
DATA SUMMIT 24 Building Real-Time Pipelines With FLaNK
 
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
Call Girls Bannerghatta Road Just Call 👗 7737669865 👗 Top Class Call Girl Ser...
 
Discover Why Less is More in B2B Research
Discover Why Less is More in B2B ResearchDiscover Why Less is More in B2B Research
Discover Why Less is More in B2B Research
 
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
VIP Model Call Girls Hinjewadi ( Pune ) Call ON 8005736733 Starting From 5K t...
 
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
Chintamani Call Girls: 🍓 7737669865 🍓 High Profile Model Escorts | Bangalore ...
 
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts ServiceCall Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
Call Girls In Shalimar Bagh ( Delhi) 9953330565 Escorts Service
 

Awesome SQL Tips and Tricks - Voxxed Days Cluj - 2019

  • 2. @vlad_mihalcea vladmihalcea.com About me • Java Champion • vladmihalcea.com • @vlad_mihalcea • vladmihalcea
  • 3. @vlad_mihalcea vladmihalcea.com InfoQ – Trends Report https://www.infoq.com/articles/architecture-trends-2019/
  • 4. @vlad_mihalcea vladmihalcea.com InfoQ – Trends Report https://www.infoq.com/articles/architecture-trends-2019/
  • 5. @vlad_mihalcea vladmihalcea.com StackOverflow Survey – Most Popular Technologies https://insights.stackoverflow.com/survey/2019
  • 6. @vlad_mihalcea vladmihalcea.com SQL is old school https://www.pexels.com/photo/antique-blur-classic-close-up-595699/
  • 7. @vlad_mihalcea vladmihalcea.com SQL – ‘70s 1970 E.F. Codd’s from IBM Relational Model 1974 D. D. Chamberlin & R. F. Boyce IBM System R 1974 Michael Stonebraker Berkeley Ingres 1979 Relational Software, Inc. Oracle V2 Marketing
  • 8. @vlad_mihalcea vladmihalcea.com SQL – ‘80s IBM System R 1981 IBM SQL/DS 1983 IBM DB2 1987 IBM DB2 for OS/2 1985 Robert Epstein Sybase Berkeley Ingres 1988 Microsoft Sybase SQL Server 1985 Michael Stonebraker POSTGRES
  • 9. @vlad_mihalcea vladmihalcea.com SQL – ‘90s 1995 David Axmark & Michael Widenius MySQL Sybase SQL Server 1993 Microsoft SQL Server POSTGRES 1996 PostgreSQL
  • 10. @vlad_mihalcea vladmihalcea.com Why is SQL still used? https://qr.ae/TWCBD5
  • 11. @vlad_mihalcea vladmihalcea.com StackOverflow Survey – Most Popular Databases https://insights.stackoverflow.com/survey/2019
  • 12. @vlad_mihalcea vladmihalcea.com StackOverflow Survey – Most Popular Databases https://insights.stackoverflow.com/survey/2019
  • 13. @vlad_mihalcea vladmihalcea.com What does SQL stand for? S? Query Language
  • 14. @vlad_mihalcea vladmihalcea.com What does SQL stand for? https://twitter.com/vlad_mihalcea/status/1172446336131596289
  • 15. @vlad_mihalcea vladmihalcea.com SQL Standard Photo by Frederick Tubiermont on Unsplash https://unsplash.com/photos/fJSRg-r7LuI
  • 17. @vlad_mihalcea vladmihalcea.com SQL:92 • In 1992, a major version of the standard was released. The specification grew from 115 pages to 580. • SQL:92 adds support for: • DATE, TIME, TIMESTAMP, INTERVAL, BIT, VARCHAR, NVARCHAR, • UNION, NATURAL JOIN, • CASE expressions, • CHECK constraints, • Type casting (e.g., CAST (expr AS type))
  • 18. @vlad_mihalcea vladmihalcea.com SQL:92 • Other SQL:92 features include: • INFORMATION_SCHEMA, • Dynamic query execution (e.g., java.sql.Statement). Previously, only prepared statements were supported. • Temporary tables, • Custom isolation levels, • Database cursors, • Scalar operations like String concatenation, date manipulation.
  • 20. @vlad_mihalcea vladmihalcea.com Fetching one-to-many relationship with pagination We need to get the first 2 post entries starting with a given string value, along with all their associated post_comment child records.
  • 21. @vlad_mihalcea vladmihalcea.com post id review post_id 1 SQL:2016 is great! 1 2 SQL:2016 is excellent! 1 3 SQL:20016 is awesome! 1 4 SQL:2011 is great! 2 5 SQL:2011 is excellent! 2 7 SQL:2008 is great! 3 id title 1 SQL:2016 2 SQL:2011 3 SQL:2008 Fetching one-to-many relationship with pagination post_comment post_id post_title comment_id comment_review 1 SQL:2016 1 SQL:2016 is great! 1 SQL:2016 2 SQL:2016 is excellent! 1 SQL:2016 3 SQL:20016 is awesome! Result set
  • 22. @vlad_mihalcea vladmihalcea.com post id review post_id 1 SQL:2016 is great! 1 2 SQL:2016 is excellent! 1 3 SQL:20016 is awesome! 1 4 SQL:2011 is great! 2 5 SQL:2011 is excellent! 2 7 SQL:2008 is great! 3 id title 1 SQL:2016 2 SQL:2011 3 SQL:2008 Fetching one-to-many relationship with pagination post_comment post_id post_title comment_id comment_review 1 SQL:2016 1 SQL:2016 is great! 1 SQL:2016 2 SQL:2016 is excellent! 1 SQL:2016 3 SQL:20016 is awesome! 2 SQL:2011 4 SQL:2011 is great! 2 SQL:2011 5 SQL:2011 is excellent! Result set
  • 23. @vlad_mihalcea vladmihalcea.com JPQL – Join fetch with Pagination List<Post> posts = entityManager .createQuery( """ select p from Post p left join fetch p.comments pc where p.title like :title order by p.id, pc.id """, Post.class) .setParameter("title", "SQL%") .setMaxResults(2) .getResultList();
  • 24. @vlad_mihalcea vladmihalcea.com JPQL – Join fetch with Pagination WARN [main]: QueryTranslatorImpl - HHH000104: firstResult/maxResults specified with collection fetch; applying in memory! SELECT p.id AS id1_0_0_, p.title AS title3_0_0_, pc.id AS id1_1_0__, pc.post_id AS post_id4_1_1_, pc.review AS review3_1_1_ FROM post p LEFT OUTER JOIN post_comment pc ON p.id = pc.post_id WHERE p.title LIKE 'SQL%' ORDER BY p.id, pc.id
  • 25. @vlad_mihalcea vladmihalcea.com SQL – Join fetch with Pagination SELECT p.id AS post_id, p.title AS post_title, pc.id AS comment_id, pc.review AS comment_review FROM post p LEFT JOIN post_comment pc ON p.id = pc.post_id WHERE p.id IN ( SELECT id FROM post WHERE p.title LIKE 'SQL%' ORDER BY id LIMIT 2 ) ORDER BY post_id, comment_id
  • 26. @vlad_mihalcea vladmihalcea.com SQL – Derived tables – Oracle Top N SELECT t.* FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t WHERE ROWNUM <= 5 ORDER BY ROWNUM We must sort the result set prior to assigning the row ranking numbers.
  • 27. @vlad_mihalcea vladmihalcea.com SQL – Derived tables – Oracle Top N SELECT t.* FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t WHERE ROWNUM <= 5 ORDER BY ROWNUM The outer query can now limit the result set size.
  • 28. @vlad_mihalcea vladmihalcea.com SQL – Derived tables – Oracle Next N SELECT t2.* FROM ( SELECT t1.*, ROWNUM AS ROW_NUM FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t1 WHERE ROWNUM <= 10 ) t2 WHERE ROW_NUM > 5 ORDER BY ROW_NUM We must sort the result set prior to assigning the row ranking numbers.
  • 29. @vlad_mihalcea vladmihalcea.com SQL – Derived tables – Oracle Next N SELECT t2.* FROM ( SELECT t1.*, ROWNUM AS ROW_NUM FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t1 WHERE ROWNUM <= 10 ) t2 WHERE ROW_NUM > 5 ORDER BY ROW_NUM The following outer query can now limit the result set size.
  • 30. @vlad_mihalcea vladmihalcea.com SQL – Derived tables – Oracle Next N SELECT t2.* FROM ( SELECT t1.*, ROWNUM AS ROW_NUM FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t1 WHERE ROWNUM <= 10 ) t2 WHERE ROW_NUM > 5 ORDER BY ROW_NUM The outer-most query can set the offset where we want to start streaming the result set back to the DB client.
  • 32. @vlad_mihalcea vladmihalcea.com SQL Standard timeline SQL:86 SQL:89 SQL:92
  • 33. @vlad_mihalcea vladmihalcea.com SQL Standard timeline SQL:86 SQL:89 SQL:92 SQL:1999 SQL:2011 SQL:2008 SQL:2006 SQL:2003 SQL:2016
  • 34. @vlad_mihalcea vladmihalcea.com SQL:1999 • In 1999, a new major version of the standard was released. • It added support for: • Boolean column type, • WITH CTE (Common Table Expression) queries and WITH RECURSIVE queries for hierarchic queries, • ROLLUP, CUBE, GROUPING SETS for GROUP BY, • Initial support for ARRAY types (e.g., UNNEST)
  • 35. @vlad_mihalcea vladmihalcea.com Pyramid of Doom SELECT t2.* FROM ( SELECT t1.*, ROWNUM AS ROW_NUM FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t1 WHERE ROWNUM <= 10 ) t2 WHERE ROW_NUM > 5 ORDER BY ROW_NUM
  • 36. @vlad_mihalcea vladmihalcea.com • Supported databases: • Oracle 9i R2 • SQL Server 2005 • PostgreSQL 8.4 • MySQL 8.0.1 • MariaDB 10.2.1 CTE (Common Table Expression)
  • 37. @vlad_mihalcea vladmihalcea.com SQL – CTE WITH p AS ( SELECT title FROM post ORDER BY created_on DESC, id DESC ), p_limit AS ( SELECT p.*, ROWNUM AS ROW_NUM FROM p WHERE ROWNUM <= 10 ) SELECT title FROM p_limit WHERE ROW_NUM > 5 ORDER BY ROWNUM
  • 38. @vlad_mihalcea vladmihalcea.com SQL – CTE WITH p AS ( SELECT title FROM post ORDER BY created_on DESC, id DESC ), p_limit AS ( SELECT p.*, ROWNUM AS ROW_NUM FROM p WHERE ROWNUM <= 10 ) SELECT title FROM p_limit WHERE ROW_NUM > 5 ORDER BY ROWNUM
  • 39. @vlad_mihalcea vladmihalcea.com SQL – CTE WITH p AS ( SELECT title FROM post ORDER BY created_on DESC, id DESC ), p_limit AS ( SELECT p.*, ROWNUM AS ROW_NUM FROM p WHERE ROWNUM <= 10 ) SELECT title FROM p_limit WHERE ROW_NUM > 5 ORDER BY ROWNUM
  • 40. @vlad_mihalcea vladmihalcea.com Fetching hierarchical data 6 + 2 + 2 + 1 + … total_score
  • 42. @vlad_mihalcea vladmihalcea.com Fetch the top 3 comment hierarchies by total score We need to get the top 3 post_comment hierarchies based on their total post_comment score.
  • 43. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – table records post_comment 4 = 1 + 2 + 2 + 1 total_score
  • 44. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – table records post_comment 3 = 1 + 1 + 1 total_score
  • 45. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – table records post_comment 9 = 1 + 10 - 2 total_score
  • 46. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – table records post_comment -5 total_score
  • 47. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – table records post_comment 0 total_score
  • 48. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching all data – application-level sorting SELECT id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 post_comment
  • 49. @vlad_mihalcea vladmihalcea.com Fetching all data – application-level sorting Map<Long, PostCommentScore> postCommentScoreMap = postCommentScores .stream() .collect(Collectors.toMap(PostCommentScore::getId, Function.identity())); List<PostCommentScore> postCommentRoots = postCommentScores .stream() .filter(pcs -> { boolean isRoot = pcs.getParentId() == null; if(!isRoot) { postCommentScoreMap.get(pcs.getParentId()).addChild(pcs); } return isRoot; }) .sorted( Comparator.comparing(PostCommentScore::getTotalScore).reversed() ) .limit(ranking) .collect(Collectors.toList());
  • 50. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – 1st level SELECT id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL Fetch all root-level comments. post_comment
  • 51. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – 2nd level WITH pc_r AS ( SELECT id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL ) SELECT * FROM pc_r UNION ALL SELECT pc.id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN pc_r ON pc_r.id = pc.parent_id post_comment
  • 52. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 Fetching hierarchical data – 2nd level WITH pc_r AS ( SELECT id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL ) SELECT * FROM pc_r UNION ALL SELECT pc.id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN pc_r ON pc_r.id = pc.parent_id post_comment
  • 53. @vlad_mihalcea vladmihalcea.com Fetching hierarchical data – Nth level This approach of merging manually (using UNION ALL) the result sets of each individual level is cumbersome and requires us knowing the number of levels upfront.
  • 54. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( ) The result set table built recursively
  • 55. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( ) We want to propagate the root_id to all comments belonging to the same hierarchy.
  • 56. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL ) Anchor member – the 1st level
  • 57. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL ) Anchor member – the 1st level
  • 58. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) Recursive member – the 2nd to Nth level
  • 59. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) Joining the current and previous levels
  • 60. @vlad_mihalcea vladmihalcea.com SQL – Recursive CTE WITH RECURSIVE post_comment_score(id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score Result set projection query
  • 61. @vlad_mihalcea vladmihalcea.com Recursive CTE – 1st level WITH RECURSIVE post_comment_score( id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 post_comment
  • 62. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 Recursive CTE – 1st level WITH RECURSIVE post_comment_score( id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score post_comment_score
  • 63. @vlad_mihalcea vladmihalcea.com Recursive CTE – 2nd level WITH RECURSIVE post_comment_score( id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 post_comment
  • 64. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 Recursive CTE – 2nd level WITH RECURSIVE post_comment_score( id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score post_comment_score
  • 65. @vlad_mihalcea vladmihalcea.com Recursive CTE – 3rd level WITH RECURSIVE post_comment_score( id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score id parent_id review created_on score post_id 1 Comment 1 2019-10-13 12:23:05 1 1 2 1 Comment 1.1 2019-10-14 13:23:10 2 1 3 1 Comment 1.2 2019-10-14 15:45:15 2 1 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 1 5 Comment 2 2019-10-13 15:23:25 1 1 6 5 Comment 2.1 2019-10-14 11:23:30 1 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 1 8 Comment 3 2019-10-15 10:15:40 1 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 1 11 Comment 4 2019-10-19 21:43:55 -5 1 12 Comment 5 2019-10-22 23:45:00 0 1 post_comment
  • 66. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Recursive CTE – 3rd level WITH RECURSIVE post_comment_score( id, root_id, post_id, parent_id, review, created_on, score) AS ( SELECT id, id, post_id, parent_id, review, created_on, score FROM post_comment WHERE post_id = 1 AND parent_id IS NULL UNION ALL SELECT pc.id, pcs.root_id, pc.post_id, pc.parent_id, pc.review, pc.created_on, pc.score FROM post_comment pc INNER JOIN post_comment_score pcs ON pc.parent_id = pcs.id ) SELECT id, parent_id, root_id, review, created_on, score FROM post_comment_score post_comment_score
  • 67. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Why use Recursive CTE? post_comment_score
  • 68. @vlad_mihalcea vladmihalcea.com Window Functions Photo by Numendil on Unsplash https://unsplash.com/photos/sSKNdbv3qNg
  • 69. @vlad_mihalcea vladmihalcea.com SQL:2003 • SQL:2003 was a minor version of SQL:1999. • It added support for: • Window Functions, • MERGE statement • SEQUNCE generator and IDENTITY column type, • XML column type
  • 70. @vlad_mihalcea vladmihalcea.com • Supported databases: • Oracle 8i • SQL Server 2005 • PostgreSQL 8.4 • MySQL 8.0.2 • MariaDB 10.2.0 Window Functions
  • 71. @vlad_mihalcea vladmihalcea.com Summing up comment scores by root_id total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ),
  • 72. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Summing comment scores – 1st root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), post_comment_score
  • 73. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score total_score 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 Comment 2.2 2019-10-14 14:45:35 1 5 Comment 2 2019-10-13 15:23:25 1 8 Comment 3 2019-10-15 10:15:40 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 Comment 3.2 2019-10-17 18:30:50 -2 11 Comment 4 2019-10-19 21:43:55 -5 12 Comment 5 2019-10-22 23:45:00 0 Summing comment scores – 1st root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), total_score_comment
  • 74. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Summing comment scores – 2nd root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), post_comment_score
  • 75. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score total_score 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 Comment 3.2 2019-10-17 18:30:50 -2 11 Comment 4 2019-10-19 21:43:55 -5 12 Comment 5 2019-10-22 23:45:00 0 Summing comment scores – 2nd root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), total_score_comment
  • 76. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Summing comment scores – 3rd root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), post_comment_score
  • 77. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score total_score 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 11 Comment 4 2019-10-19 21:43:55 -5 12 Comment 5 2019-10-22 23:45:00 0 Summing comment scores – 3rd root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), total_score_comment
  • 78. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Summing comment scores – 4th root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), post_comment_score
  • 79. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score total_score 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 Summing comment scores – 4th root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), total_score_comment
  • 80. @vlad_mihalcea vladmihalcea.com id parent_id root_id review created_on score 1 1 Comment 1 2019-10-13 12:23:05 1 5 5 Comment 2 2019-10-13 15:23:25 1 8 8 Comment 3 2019-10-15 10:15:40 1 11 11 Comment 4 2019-10-19 21:43:55 -5 12 12 Comment 5 2019-10-22 23:45:00 0 2 1 1 Comment 1.1 2019-10-14 13:23:10 2 3 1 1 Comment 1.2 2019-10-14 15:45:15 2 6 5 5 Comment 2.1 2019-10-14 11:23:30 1 7 5 5 Comment 2.2 2019-10-14 14:45:35 1 9 8 8 Comment 3.1 2019-10-16 11:15:45 10 10 8 8 Comment 3.2 2019-10-17 18:30:50 -2 4 3 1 Comment 1.2.1 2019-10-15 10:15:20 1 Summing comment scores – 5th root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), post_comment_score
  • 81. @vlad_mihalcea vladmihalcea.com id parent_id review created_on score total_score 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 0 Summing comment scores – 5th root total_score_comment AS ( SELECT id, parent_id, review, created_on, score, SUM(score) OVER ( PARTITION BY root_id ) AS total_score FROM post_comment_score ), total_score_comment
  • 82. @vlad_mihalcea vladmihalcea.com Ranking comment total scores total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ),
  • 83. @vlad_mihalcea vladmihalcea.com Ranking comment total scores – 1st rank total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ), id parent_id review created_on score total_score 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 0 total_score_comme nt
  • 84. @vlad_mihalcea vladmihalcea.com Ranking comment total scores – 1st rank total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ), id parent_id review created_on score total_score ranking 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 1 Comment 1 2019-10-13 12:23:05 1 6 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 0 total_score_ranking
  • 85. @vlad_mihalcea vladmihalcea.com Ranking comment total scores – 2nd rank total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ), id parent_id review created_on score total_score ranking 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2 1 Comment 1 2019-10-13 12:23:05 1 6 2 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 5 Comment 2 2019-10-13 15:23:25 1 3 8 Comment 3 2019-10-15 10:15:40 1 9 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 0 total_score_ranking
  • 86. @vlad_mihalcea vladmihalcea.com Ranking comment total scores – 3rd rank total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ), id parent_id review created_on score total_score ranking 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2 1 Comment 1 2019-10-13 12:23:05 1 6 2 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3 5 Comment 2 2019-10-13 15:23:25 1 3 3 8 Comment 3 2019-10-15 10:15:40 1 9 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 0 total_score_ranking
  • 87. @vlad_mihalcea vladmihalcea.com Ranking comment total scores – 4th rank total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ), id parent_id review created_on score total_score ranking 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2 1 Comment 1 2019-10-13 12:23:05 1 6 2 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3 5 Comment 2 2019-10-13 15:23:25 1 3 3 8 Comment 3 2019-10-15 10:15:40 1 9 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 11 Comment 4 2019-10-19 21:43:55 -5 -5 12 Comment 5 2019-10-22 23:45:00 0 0 4 total_score_ranking
  • 88. @vlad_mihalcea vladmihalcea.com Ranking comment total scores – 5th rank total_score_ranking AS ( SELECT id, parent_id, review, created_on, score, total_score, DENSE_RANK() OVER ( ORDER BY total_score DESC ) ranking FROM total_score_comment ), id parent_id review created_on score total_score ranking 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2 1 Comment 1 2019-10-13 12:23:05 1 6 2 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3 5 Comment 2 2019-10-13 15:23:25 1 3 3 8 Comment 3 2019-10-15 10:15:40 1 9 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 11 Comment 4 2019-10-19 21:43:55 -5 -5 5 12 Comment 5 2019-10-22 23:45:00 0 0 4 total_score_ranking
  • 89. @vlad_mihalcea vladmihalcea.com Filtering by the comment total score SELECT id, parent_id, review, created_on, score, total_score FROM total_score_ranking WHERE ranking <= 3 ORDER BY total_score DESC, id ASC
  • 90. @vlad_mihalcea vladmihalcea.com Filtering by the comment total score SELECT id, parent_id, review, created_on, score, total_score FROM total_score_ranking WHERE ranking <= 3 ORDER BY total_score DESC, id ASC id parent_id review created_on score total_score ranking 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 2 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 2 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 2 1 Comment 1 2019-10-13 12:23:05 1 6 2 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 3 5 Comment 2 2019-10-13 15:23:25 1 3 3 8 Comment 3 2019-10-15 10:15:40 1 9 1 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 1 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 11 Comment 4 2019-10-19 21:43:55 -5 -5 5 12 Comment 5 2019-10-22 23:45:00 0 0 4 total_score_ranking
  • 91. @vlad_mihalcea vladmihalcea.com Filtering by the comment total score SELECT id, parent_id, review, created_on, score, total_score FROM total_score_ranking WHERE ranking <= 3 ORDER BY total_score DESC, id ASC id parent_id review created_on score total_score 8 Comment 3 2019-10-15 10:15:40 1 9 9 8 Comment 3.1 2019-10-16 11:15:45 10 9 10 8 Comment 3.2 2019-10-17 18:30:50 -2 9 1 Comment 1 2019-10-13 12:23:05 1 6 2 1 Comment 1.1 2019-10-14 13:23:10 2 6 3 1 Comment 1.2 2019-10-14 15:45:15 2 6 4 3 Comment 1.2.1 2019-10-15 10:15:20 1 6 5 Comment 2 2019-10-13 15:23:25 1 3 6 5 Comment 2.1 2019-10-14 11:23:30 1 3 7 5 Comment 2.2 2019-10-14 14:45:35 1 3 Result set
  • 92. @vlad_mihalcea vladmihalcea.com Application-level vs database processing 20 104 656 2040 4640 15024 34880 0 10 20 30 40 50 60 70 80 90 100 Data set size Time(ms) Application-level Recursive CTE
  • 93. @vlad_mihalcea vladmihalcea.com SQL:2003 • SQL:2003 was a minor version of SQL:1999. • It added support for: • Window Functions, • MERGE statement • SEQUNCE generator and IDENTITY column type, • XML column type
  • 94. @vlad_mihalcea vladmihalcea.com • Supported databases: • Oracle 9i • SQL Server 2008 • PostgreSQL and MySQL offer non-standard UPSERT alternatives. MERGE
  • 95. @vlad_mihalcea vladmihalcea.com Oracle MERGE – Ignore on constraint violation MERGE INTO book USING (SELECT 1 FROM dual) ON (id = 1) WHEN NOT MATCHED THEN INSERT ( id, title, isbn ) VALUES ( 1, 'High-Performance Java Persistence', '978-9730228236' )
  • 96. @vlad_mihalcea vladmihalcea.com Oracle MERGE – UPDATE on constraint violation MERGE INTO book USING (SELECT 1 FROM dual) ON (id = 1) WHEN MATCHED THEN UPDATE SET title = 'High-Performance Java Persistence, 2nd Edition', isbn = '978-9730228236' WHEN NOT MATCHED THEN INSERT ( id, title, isbn ) VALUES ( 1, 'High-Performance Java Persistence', '978-9730228236' )
  • 97. @vlad_mihalcea vladmihalcea.com SQL:2006 • SQL:2006 added support for: • XQuery, • SQL/XML functions (e.g., XMLELEMENT)
  • 98. @vlad_mihalcea vladmihalcea.com SQL:2008 • SQL:2008 added support for: • TRUNCATE TABLE, • Multiple WHEN clauses in CASE expressions, • INSTEAD OF database triggers (override INSERT, UPDATE, DELETE), • XQuery regular expression/pattern matching, • Derived column list to override a derived table column names, • Standard pagination using: • FETCH FIRST N ROWS ONLY • OFFSET M ROWS
  • 99. @vlad_mihalcea vladmihalcea.com SQL – Oracle legacy Top N SELECT t.* FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t WHERE ROWNUM <= 5 ORDER BY ROWNUM
  • 100. @vlad_mihalcea vladmihalcea.com SQL – Standard Top N SELECT title FROM post ORDER BY created_on DESC, id DESC FETCH FIRST 5 ROWS ONLY
  • 101. @vlad_mihalcea vladmihalcea.com SQL – Oracle legacy Next N SELECT t2.* FROM ( SELECT t1.*, ROWNUM AS ROW_NUM FROM ( SELECT title FROM post ORDER BY created_on DESC, id DESC ) t1 WHERE ROWNUM <= 10 ) t2 WHERE ROW_NUM > 5 ORDER BY ROW_NUM
  • 102. @vlad_mihalcea vladmihalcea.com SQL – Standard Next N SELECT title FROM post ORDER BY created_on DESC, id DESC OFFSET 5 ROWS FETCH NEXT 5 ROWS ONLY
  • 103. @vlad_mihalcea vladmihalcea.com SQL:2011 • SQL: 2011 added support for • Temporal database, • System-versioned tables
  • 104. @vlad_mihalcea vladmihalcea.com SQL:2016 • SQL: 2016 added support for: • JSON, • MATCH_RECOGNIZE (Row Pattern Recognition), • LISTAGG (aggregate multiple values to a delimited string value), • DECFLOAT column type (e.g., decimal floating arithmetic), • Date and Time formatting (e.g., CAST(.. AS .. FORMAT ..), EXTRACT(.. FROM <datetime>))
  • 105. @vlad_mihalcea vladmihalcea.com • Supported databases: • Oracle 12c • SQL Server 2016 • PostgreSQL 9.2 • MySQL 5.6 • PostgreSQL and MySQL offer non-standard alternatives. JSON
  • 106. @vlad_mihalcea vladmihalcea.com MySQL – storing JSON CREATE TABLE book ( id bigint NOT NULL PRIMARY KEY, isbn VARCHAR(15), properties JSON )
  • 107. @vlad_mihalcea vladmihalcea.com MySQL – Get scalar attribute SELECT id, CAST( properties -> '$.price' AS DECIMAL(4, 2) ) AS price FROM book WHERE properties -> '$.title' = 'High-Performance Java Persistence' Without casting to DECIMAL, the result will be returned as a String.
  • 108. @vlad_mihalcea vladmihalcea.com MySQL – Get scalar attribute id isbn properties 1 978-9730228236 { "title":"High-Performance Java Persistence", "author":"Vlad Mihalcea", "publisher":"Amazon", "price":44.99, "reviews":[ … ] } book SELECT id, CAST( properties -> '$.price' AS DECIMAL(4, 2) ) AS price FROM book WHERE properties -> '$.title' = 'High-Performance Java Persistence' id price 1 44.99 Result set
  • 109. @vlad_mihalcea vladmihalcea.com SELECT id, properties -> '$.reviews' AS reviews FROM book WHERE isbn = '978-9730228236' MySQL – Get JSON object
  • 110. @vlad_mihalcea vladmihalcea.com MySQL – Get JSON object SELECT id, properties -> '$.reviews' AS reviews FROM book WHERE isbn = '978-9730228236' id isbn properties 1 978-9730228236 { "title":"High-Performance Java Persistence", "author":"Vlad Mihalcea", "publisher":"Amazon", "price":44.99, "reviews":[ { "reviewer":"Cristiano", "review":"Excellent book to understand Java Persistence", "date":"2017-11-14", "rating":5 }, { "reviewer":"T.W", "review":"The best JPA ORM book out there", "date":"2019-01-27", "rating":5 }, { "reviewer":"Shaikh", "review":"The most informative book", "date":"2016-12-24", "rating":4 } ] } book id reviews 1 [ {..}, {..}, {..} ] Result set
  • 111. @vlad_mihalcea vladmihalcea.com SELECT r.* FROM book, JSON_TABLE( properties, '$.reviews[*]' COLUMNS( reviewer VARCHAR(4000) PATH '$.reviewer', review VARCHAR(4000) PATH '$.review', review_date DATETIME PATH '$.date’, rating INT PATH '$.rating' ) ) AS r WHERE isbn = '978-9730228236' MySQL – JSON to SQL table
  • 112. @vlad_mihalcea vladmihalcea.com SELECT r.* FROM book, JSON_TABLE( properties, '$.reviews[*]' COLUMNS( reviewer VARCHAR(4000) PATH '$.reviewer', review VARCHAR(4000) PATH '$.review', review_date DATETIME PATH '$.date’, rating INT PATH '$.rating' ) ) AS r WHERE isbn = '978-9730228236' MySQL – JSON to SQL table "reviews":[ { "reviewer":"Cristiano", "review":"Excellent book to understand Java Persistence", "date":"2017-11-14", "rating":5 }, { "reviewer":"T.W", "review":"The best JPA ORM book out there", "date":"2019-01-27", "rating":5 }, { "reviewer":"Shaikh", "review":"The most informative book", "date":"2016-12-24", "rating":4 } ] reviewer review review_date rating book
  • 113. @vlad_mihalcea vladmihalcea.com SELECT r.* FROM book, JSON_TABLE( properties, '$.reviews[*]' COLUMNS( reviewer VARCHAR(4000) PATH '$.reviewer', review VARCHAR(4000) PATH '$.review', review_date DATETIME PATH '$.date’, rating INT PATH '$.rating' ) ) AS r WHERE isbn = '978-9730228236' MySQL – JSON to SQL table "reviews":[ { "reviewer":"Cristiano", "review":"Excellent book to understand Java Persistence", "date":"2017-11-14", "rating":5 }, { "reviewer":"T.W", "review":"The best JPA ORM book out there", "date":"2019-01-27", "rating":5 }, { "reviewer":"Shaikh", "review":"The most informative book", "date":"2016-12-24", "rating":4 } ] reviewer review review_date rating Cristiano Excellent book to understand Java Persistence 14-Nov-2017 5 book
  • 114. @vlad_mihalcea vladmihalcea.com SELECT r.* FROM book, JSON_TABLE( properties, '$.reviews[*]' COLUMNS( reviewer VARCHAR(4000) PATH '$.reviewer', review VARCHAR(4000) PATH '$.review', review_date DATETIME PATH '$.date’, rating INT PATH '$.rating' ) ) AS r WHERE isbn = '978-9730228236' MySQL – JSON to SQL table "reviews":[ { "reviewer":"Cristiano", "review":"Excellent book to understand Java Persistence", "date":"2017-11-14", "rating":5 }, { "reviewer":"T.W", "review":"The best JPA ORM book out there", "date":"2019-01-27", "rating":5 }, { "reviewer":"Shaikh", "review":"The most informative book", "date":"2016-12-24", "rating":4 } ] reviewer review review_date rating Cristiano Excellent book to understand Java Persistence 14-Nov-2017 5 T.W The best JPA ORM book out there 27-Jan-2019 5 book
  • 115. @vlad_mihalcea vladmihalcea.com SELECT r.* FROM book, JSON_TABLE( properties, '$.reviews[*]' COLUMNS( reviewer VARCHAR(4000) PATH '$.reviewer', review VARCHAR(4000) PATH '$.review', review_date DATETIME PATH '$.date’, rating INT PATH '$.rating' ) ) AS r WHERE isbn = '978-9730228236' MySQL – JSON to SQL table "reviews":[ { "reviewer":"Cristiano", "review":"Excellent book to understand Java Persistence", "date":"2017-11-14", "rating":5 }, { "reviewer":"T.W", "review":"The best JPA ORM book out there", "date":"2019-01-27", "rating":5 }, { "reviewer":"Shaikh", "review":"The most informative book", "date":"2016-12-24", "rating":4 } ] reviewer review review_date rating Cristiano Excellent book to understand Java Persistence 14-Nov-2017 5 T.W The best JPA ORM book out there 27-Jan-2019 5 Shaikh The most informative book 24-Dec-2016 4book
  • 116. @vlad_mihalcea vladmihalcea.com SQL timeline SQL NoSQL NewSQL 1974 2009 2011
  • 118. @vlad_mihalcea vladmihalcea.com CockroachDB – SQL support https://www.cockroachlabs.com/docs/v19.1/sql-statements.html
  • 119. @vlad_mihalcea vladmihalcea.com VoltDB – SQL support https://www.voltdb.com/product/features-benefits/sql-database/
  • 120. @vlad_mihalcea vladmihalcea.com VoltDB – SQL support https://www.voltdb.com/product/features-benefits/sql-database/
  • 121. @vlad_mihalcea vladmihalcea.com VoltDB – SQL support https://www.voltdb.com/product/features-benefits/sql-database/
  • 122. @vlad_mihalcea vladmihalcea.com Google BigQuery – SQL support https://cloud.google.com/bigquery/docs/release-notes#March_23_2016
  • 123. @vlad_mihalcea vladmihalcea.com Google Spanner – SQL support https://static.googleusercontent.com/media/research.google.com/en//pubs/archive/46103.pdf
  • 124. @vlad_mihalcea vladmihalcea.com Thank you • Twitter: @vlad_mihalcea • Blog: https://vladmihalcea.com/ • Courses: https://vladmihalcea.com/courses/ • Training: https://vladmihalcea.com/trainings/ • Book: https://vladmihalcea.com/books/high-performance-java-persistence/