SlideShare a Scribd company logo
@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

PDF
JPA and Hibernate Performance Tips
PDF
High-Performance JDBC Voxxed Bucharest 2016
PDF
High-Performance Hibernate - JDK.io 2018
PPTX
Advance java session 5
PDF
Query Optimization with MySQL 5.7 and MariaDB 10: Even newer tricks
PPTX
Confoo 2021 -- MySQL New Features
PDF
The art of querying – newest and advanced SQL techniques
PPTX
Oracle Database 12c Release 2 - New Features On Oracle Database Exadata Expr...
JPA and Hibernate Performance Tips
High-Performance JDBC Voxxed Bucharest 2016
High-Performance Hibernate - JDK.io 2018
Advance java session 5
Query Optimization with MySQL 5.7 and MariaDB 10: Even newer tricks
Confoo 2021 -- MySQL New Features
The art of querying – newest and advanced SQL techniques
Oracle Database 12c Release 2 - New Features On Oracle Database Exadata Expr...

What's hot (20)

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

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

KEY
PostgreSQL
PDF
Cassandra Day Atlanta 2015: Data Modeling 101
PDF
Cassandra Day London 2015: Data Modeling 101
PDF
Cassandra Day Chicago 2015: Apache Cassandra Data Modeling 101
PPTX
Modern sql
PDF
Introduction to data modeling with apache cassandra
PDF
Apache Cassandra & Data Modeling
PDF
Introduction to Data Modeling with Apache Cassandra
PPT
MY SQL
PPTX
Sql analytic queries tips
PDF
Efficient Pagination Using MySQL
PDF
PPC2009_yahoo_mysql_pagination
PDF
MIS5101 WK10 Outcome Measures
PDF
Database Design most common pitfalls
PDF
2000 lines of java or 50 lines of sql the choice is yours - Lukas Eder
PDF
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
PDF
DataDay 2023 Presentation
PDF
Oracle Material.pdf
PPTX
C*ollege Credit: Creating Your First App in Java with Cassandra
PDF
Structured Query Language (SQL) - An Introduction
PostgreSQL
Cassandra Day Atlanta 2015: Data Modeling 101
Cassandra Day London 2015: Data Modeling 101
Cassandra Day Chicago 2015: Apache Cassandra Data Modeling 101
Modern sql
Introduction to data modeling with apache cassandra
Apache Cassandra & Data Modeling
Introduction to Data Modeling with Apache Cassandra
MY SQL
Sql analytic queries tips
Efficient Pagination Using MySQL
PPC2009_yahoo_mysql_pagination
MIS5101 WK10 Outcome Measures
Database Design most common pitfalls
2000 lines of java or 50 lines of sql the choice is yours - Lukas Eder
Simon Elliston Ball – When to NoSQL and When to Know SQL - NoSQL matters Barc...
DataDay 2023 Presentation
Oracle Material.pdf
C*ollege Credit: Creating Your First App in Java with Cassandra
Structured Query Language (SQL) - An Introduction
Ad

Recently uploaded (20)

PDF
Microsoft 365 products and services descrption
PPTX
Managing Community Partner Relationships
PDF
Systems Analysis and Design, 12th Edition by Scott Tilley Test Bank.pdf
PPT
ISS -ESG Data flows What is ESG and HowHow
PDF
Transcultural that can help you someday.
PDF
Global Data and Analytics Market Outlook Report
PPTX
sac 451hinhgsgshssjsjsjheegdggeegegdggddgeg.pptx
PDF
Votre score augmente si vous choisissez une catégorie et que vous rédigez une...
PPTX
Pilar Kemerdekaan dan Identi Bangsa.pptx
PDF
Data Engineering Interview Questions & Answers Batch Processing (Spark, Hadoo...
PPTX
(Ali Hamza) Roll No: (F24-BSCS-1103).pptx
PPTX
A Complete Guide to Streamlining Business Processes
PPTX
retention in jsjsksksksnbsndjddjdnFPD.pptx
PDF
annual-report-2024-2025 original latest.
PDF
Introduction to the R Programming Language
PPTX
Topic 5 Presentation 5 Lesson 5 Corporate Fin
PDF
[EN] Industrial Machine Downtime Prediction
PDF
Tetra Pak Index 2023 - The future of health and nutrition - Full report.pdf
PPTX
Microsoft-Fabric-Unifying-Analytics-for-the-Modern-Enterprise Solution.pptx
PPTX
STERILIZATION AND DISINFECTION-1.ppthhhbx
Microsoft 365 products and services descrption
Managing Community Partner Relationships
Systems Analysis and Design, 12th Edition by Scott Tilley Test Bank.pdf
ISS -ESG Data flows What is ESG and HowHow
Transcultural that can help you someday.
Global Data and Analytics Market Outlook Report
sac 451hinhgsgshssjsjsjheegdggeegegdggddgeg.pptx
Votre score augmente si vous choisissez une catégorie et que vous rédigez une...
Pilar Kemerdekaan dan Identi Bangsa.pptx
Data Engineering Interview Questions & Answers Batch Processing (Spark, Hadoo...
(Ali Hamza) Roll No: (F24-BSCS-1103).pptx
A Complete Guide to Streamlining Business Processes
retention in jsjsksksksnbsndjddjdnFPD.pptx
annual-report-2024-2025 original latest.
Introduction to the R Programming Language
Topic 5 Presentation 5 Lesson 5 Corporate Fin
[EN] Industrial Machine Downtime Prediction
Tetra Pak Index 2023 - The future of health and nutrition - Full report.pdf
Microsoft-Fabric-Unifying-Analytics-for-the-Modern-Enterprise Solution.pptx
STERILIZATION AND DISINFECTION-1.ppthhhbx

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/