[Day 33] SQL Advanced - SQL Advanced Skills - CTE and Recursive Query (SQL Xiao Xuzhu)

Sending back to the city – " 100 days proficient in MYSQL from entry to employment"

Zero. Foreword

Today is the 33rd day of learning SQL check-in , and every day I will provide an article for group members to read ( no subscription payment required ).

I hope that everyone will think for themselves first, if you really have no idea, then read the following problem-solving ideas, and implement it again by yourself. In the Xiaoxuzhu JAVA community, the corresponding [check-in stickers] check-in, today's task is completed, and develop a good habit of learning to check-in every day.

​ Brother Xuzhu will organize everyone to study the same article together, so if you have any questions, you can ask them in the group. Friends in the group can help you quickly. One person can go fast, and a group of people can go very fast. How lucky it is to have comrades-in-arms who study and communicate together.

​ My learning strategy is very simple, question sea strategy + Feynman learning method. If you can implement all these questions seriously, it means that SQL has successfully established its foundation. For the advanced learning later, you can continue to follow me and walk towards the road of architect together.

Today's learning content is: SQL advanced skills - CTE and recursive query

1. Exercise topics

topic link difficulty
Get a continuous interval ★★★☆☆

Two, SQL ideas

Get a continuous interval

insert image description here
insert image description here

Initialization data

这里写入初始化表结构,初始化数据的sql

What is a CTE query

Since MySQL 8.x, the MySQL database supports the Common Table Expression (CTE) function, which can be implemented through the WITH statement. CTEs can be divided into two types: non-recursive common table expressions and recursive common table expressions.

In a traditional subquery, if a derived table is referenced twice, it can cause MySQL performance problems. However, when using a common table expression (CTE) query, the subquery will only be referenced once, which is one of the important reasons for using CTE.

non-recursive CTE

Before MySQL 8.0, subquery statements were required to implement complex queries on data tables, but the performance of SQL statements in this way was low, and the derived tables of subqueries could not be referenced multiple times. However, with the introduction of Common Table Expressions (CTE), the writing of complex SQL has become easier and the performance of data queries has also been improved.

Non-recursive CTE syntax:

WITH cte_name (column1, column2, ...) AS (
    SELECT ...
    FROM ...
    WHERE ...
)
SELECT ...
FROM cte_name;

Among them, cte_name is the name of the common table expression, which can be customized;
column1, column2, etc. are the column names, which can also be customized;
the SELECT statement in as is the query statement used to create the common table expression;
the final SELECT statement is Used to query the results of common table expressions.
CTEs can be better understood by comparing queries with subqueries and common table expressions (CTEs). For example, running the following SQL statement on the MySQL command line can achieve the effect of a subquery.
Actual combat: using subqueries to obtain information about the current year

SELECT * FROM   (SELECT YEAR(NOW())) AS year;

insert image description here

Use the CTE to implement the query:

WITH year AS
(SELECT YEAR(NOW()))
SELECT * FROM year;

insert image description here
It is also possible to define multiple query fields in the CTE statement:

WITH cte_year_month (year, month) AS
(SELECT YEAR(NOW()) AS year, MONTH(NOW()) AS month)
 SELECT * FROM cte_year_month;

insert image description here

Multiple CTEs can also refer to each other:

WITH cte1(cte1_year, cte1_month) AS
(SELECT YEAR(NOW()) AS cte1_year, MONTH(NOW()) AS cte1_month),
cte2(cte2_year, cte2_month) AS
(SELECT (cte1_year+1) AS cte2_year, (cte1_month + 1) AS cte2_month FROM cte1) 
 SELECT * FROM cte1 JOIN cte2;

insert image description here
Note:
1. cte1 is referenced in the definition of cte2.
2. When multiple common table expressions (CTEs) are defined in an SQL statement, each CTE needs to be separated by a comma.

Recursive CTE

A subquery of a recursive common table expression (CTE) can refer to itself, so it needs to be implemented using a specific syntax format. Compared with non-recursive CTE, the grammatical format of recursive CTE has one more keyword RECURSIVE.
The syntax of a recursive CTE is as follows:

WITH RECURSIVE cte_name (column1, column2, ...) AS (
    SELECT ...
    FROM ...
    WHERE ...
    UNION [ALL]
    SELECT ...
    FROM cte_name
    WHERE ...
)
SELECT ...
FROM cte_name;

Among them, cte_name is the name of the common table expression, which can be customized;
column1, column2, etc. are the column names, which can also be customized;
the SELECT statement is used to create the query statement of the common table expression;
UNION [ALL] is used to combine The results of the recursive query are merged with the results of the previous query; the
final SELECT statement is used to query the results of common table expressions.

There are two kinds of subqueries in a recursive common table expression (CTE): a seed query and a recursive query. The seed query is used to initialize the query data, and will not refer to itself in the query; while the recursive query refers to the query itself according to certain rules on the basis of the seed query. These two queries need to use UNION, UNION ALL or UNION DISTINCT statement to connect.

Actual combat:
Use recursive CTE to output a sequence of 1 to 10 on the MySQL command line.

WITH RECURSIVE cte_num(num) AS 
(SELECT 1 UNION ALL SELECT num + 1 FROM cte_num WHERE num < 10 )
SELECT * FROM cte_num;

insert image description here

Recursive CTE queries are very convenient for traversing organized and hierarchical data.
Actual combat:
Create an area data table t_area, which contains information of provinces and cities.

CREATE TABLE t_area(
   id INT NOT NULL,
   name VARCHAR(30),
  pid INT
  );

insert image description here
Insert test data into the t_area data table.

INSERT INTO t_area
   (id, name, pid)
     VALUES
    (1, '福建省', NULL),
     (2, '厦门市', 1),
     (3, '思明区', 2),
    (4, '湖里区', 2),
    (5, '河北省', NULL),
    (6, '廊坊市', 5),
    (7, '安次区', 6);

insert image description here
insert image description here
Use recursive CTE to query the hierarchical relationship in the t_area data table:

WITH RECURSIVE area_depth(id, name, path) AS
    (
    SELECT id, name, CAST(id AS CHAR(300))
    FROM t_area WHERE pid IS NULL
    UNION ALL
     SELECT a.id, a.name, CONCAT(ad.path, ',', a.id)
     FROM area_depth AS ad 
    JOIN t_area AS a
     ON ad.id = a.pid
     )
     SELECT * FROM area_depth ORDER BY path;

insert image description here

Limitations of recursive CTEs

Recursive CTE query statement must contain a condition to stop recursion. If no stop condition is set, MySQL will automatically stop the query and report an error according to the configuration information. MySQL provides two configuration items by default to stop recursive CTE.

  • cte_max_recursion_depth: When defining a recursive CTE query, if no recursive termination condition is set, MySQL will throw an error when the number of executions set by the cte_max_recursion_depth parameter is reached.
  • max_execution_time: max_execution_time is a parameter used to set the maximum execution time of the SQL statement in milliseconds. When the execution time of the SQL statement exceeds the value set by this parameter, MySQL will throw an error.

Actual combat: For the following recursive CTE that does not set the query termination condition, MySQL will throw an error message and terminate the query

WITH RECURSIVE cte_num(num) AS
    (
     SELECT 1
    UNION ALL
    SELECT num+1 FROM cte_num
    )
   SELECT * FROM cte_num;

ERROR 3636 (HY000): Recursive query aborted after 1001 iterations. Try increasing @@cte_max_recursion_depth to a larger value.

The problem is: when no termination condition is set for the recursive CTE, MySQL will throw an error message at the 1001st query by default and terminate the query.
insert image description here
Check the default value of the cte_max_recursion_depth parameter:
insert image description here
Therefore: the default value of the cte_max_recursion_depth parameter is 1000, which is why MySQL will throw an error and terminate the query by default at the 1001st query.

Actual combat: max_execution_time configuration
Set the cte_max_recursion_depth parameter to a large number

SET SESSION cte_max_recursion_depth=999999999;
SHOW VARIABLES LIKE 'cte_max%';

insert image description here
View the default value of the max_execution_time parameter in MySQL:

SHOW VARIABLES LIKE 'max_execution%';

insert image description here
In MySQL, the value of the max_execution_time parameter is milliseconds, and the default is 0, which means there is no limit. Here, the value of max_execution_time is set to 1s at the MySQL session level.

SET SESSION max_execution_time=1000; 
SHOW VARIABLES LIKE 'max_execution%';

insert image description here
When the execution time of the SQL statement exceeds the value set by max_execution_time, MySQL reports an error.

WITH RECURSIVE cte(n) AS
    (
    SELECT 1
    UNION ALL
     SELECT n+1 FROM CTE
     )
     SELECT * FROM cte;

ERROR 3024 (HY000): Query execution was interrupted, maximum statement execution time exceeded

insert image description here
The default recursion termination mechanism provided by MySQL (cte_max_recursion_depth and max_execution_time configuration items) effectively prevents the problem of infinite recursion.

Note: According to actual needs, explicitly set the condition for recursive termination in the SQL statement of CTE. Do not rely on MySQL's default mechanism for terminating recursion.

3. Summary

This article shares what is CTE query, introduces non-recursive CTE and recursive CTE, and introduces how to use CTE with practical examples.
Recursive query is a query method based on CTE, which can be used to process data with hierarchical structure, such as organizational structure, tree structure, etc. Recursive queries implement hierarchy traversal and query by recursively referencing itself.

Finally, the recursive CTE limits the cte_max_recursion_depth and max_execution_time parameters, which should be paid special attention to in daily work.

So, um, the answer to this question is optional. . Tell Brother Xu Zhu loudly in the comment area.

4. Reference

MySQL Advanced Skills Tree – “SQL Advanced Skills –” CTE and Recursive Query

I'm Brother Xuzhu, see you tomorrow~

Guess you like

Origin blog.csdn.net/shi_hong_fei_hei/article/details/129910184