[Día 33] SQL avanzado - Habilidades avanzadas de SQL - CTE y consulta recursiva (SQL Xiao Xuzhu)

Envío de regreso a la ciudad: " 100 días competentes en MYSQL desde el ingreso al empleo"

Cero Prólogo

Hoy es el día 33 de aprendizaje de registro de SQL , y todos los días proporcionaré un artículo para que lean los miembros del grupo ( no se requiere pago de suscripción ).

Espero que todos piensen por sí mismos primero, si realmente no tiene idea, lea las siguientes ideas para resolver problemas y vuelva a implementarlas usted mismo. En la comunidad Xiaoxuzhu JAVA, el correspondiente registro de [etiquetas adhesivas de registro], la tarea de hoy se completa y desarrolla un buen hábito de aprender a registrarse todos los días.

El hermano Xuzhu organizará a todos para que estudien el mismo artículo juntos, por lo que si tiene alguna pregunta, puede hacerla en el grupo. Los amigos del grupo pueden ayudarlo rápidamente. Una persona puede ir rápido y un grupo de personas puede ir. muy rápido Que suerte tener compañeros de armas que estudian y se comunican juntos.

​ Mi estrategia de aprendizaje es muy simple, estrategia de mar de preguntas + método de aprendizaje Feynman. Si puede implementar todas estas preguntas con seriedad, significa que SQL ha establecido con éxito su base. Para el aprendizaje avanzado posterior, pueden continuar siguiéndome y caminar juntos hacia el camino del arquitecto.

El contenido de aprendizaje de hoy es: Habilidades avanzadas de SQL - CTE y consulta recursiva

1. Temas de ejercicios

enlace de tema dificultad
Obtener un intervalo continuo ★★★☆☆

Dos, ideas SQL

Obtener un intervalo continuo

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí

Datos de inicialización

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

¿Qué es una consulta CTE?

Desde MySQL 8.x, la base de datos MySQL admite la función Common Table Expression (CTE), que se puede implementar a través de la instrucción WITH. Las CTE se pueden dividir en dos tipos: expresiones de tablas comunes no recursivas y expresiones de tablas comunes recursivas.

En una subconsulta tradicional, si se hace referencia dos veces a una tabla derivada, puede causar problemas de rendimiento de MySQL. Sin embargo, cuando se usa una consulta de expresión de tabla común (CTE), la subconsulta solo se referenciará una vez, que es una de las razones importantes para usar CTE.

CTE no recursivo

Antes de MySQL 8.0, se requerían declaraciones de subconsultas para implementar consultas complejas en tablas de datos, pero el rendimiento de las declaraciones SQL de esta manera era bajo y las tablas derivadas de subconsultas no podían referenciarse varias veces. Sin embargo, con la introducción de Common Table Expressions (CTE), la escritura de SQL complejo se ha vuelto más fácil y también se ha mejorado el rendimiento de las consultas de datos.

Sintaxis CTE no recursiva:

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

Entre ellos, cte_name es el nombre de la expresión de tabla común, que se puede personalizar;
column1, column2, etc. son los nombres de las columnas, que también se pueden personalizar;
la declaración SELECT en as es la declaración de consulta utilizada para crear la tabla común expresión;
la instrucción SELECT final se utiliza para consultar los resultados de expresiones de tabla comunes.
Las CTE se pueden entender mejor comparando consultas con subconsultas y expresiones de tabla comunes (CTE). Por ejemplo, ejecutar la siguiente instrucción SQL en la línea de comandos de MySQL puede lograr el efecto de una subconsulta.
Combate real: uso de subconsultas para obtener información sobre el año en curso

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

inserte la descripción de la imagen aquí

Use el CTE para implementar la consulta:

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

inserte la descripción de la imagen aquí
También es posible definir múltiples campos de consulta en la declaración CTE:

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

inserte la descripción de la imagen aquí

Múltiples CTE también pueden referirse entre sí:

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;

inserte la descripción de la imagen aquí
Nota:
1. Se hace referencia a cte1 en la definición de cte2
2. Cuando se definen varias expresiones de tabla comunes (CTE) en una instrucción SQL, cada CTE debe estar separada por una coma.

CTE recursivo

Una subconsulta de una expresión de tabla común recursiva (CTE) puede referirse a sí misma, por lo que debe implementarse utilizando un formato de sintaxis específico. Comparado con CTE no recursivo, el formato gramatical de CTE recursivo tiene una palabra clave más RECURSIVO.
La sintaxis de un CTE recursivo es la siguiente:

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

Entre ellos, cte_name es el nombre de la expresión de tabla común, que se puede personalizar;
column1, column2, etc. son los nombres de las columnas, que también se pueden personalizar;
la declaración SELECT se usa para crear la declaración de consulta de la expresión de tabla común ;
UNION [ALL] se usa para combinar Los resultados de la consulta recursiva se fusionan con los resultados de la consulta anterior; la
instrucción SELECT final se usa para consultar los resultados de expresiones de tabla comunes.

Hay dos tipos de subconsultas en una expresión de tabla común recursiva (CTE): una consulta semilla y una consulta recursiva. La consulta semilla se usa para inicializar los datos de la consulta y no se referirá a sí misma en la consulta, mientras que la consulta recursiva se refiere a la consulta misma de acuerdo con ciertas reglas sobre la base de la consulta semilla. Estas dos consultas deben usar la instrucción UNION, UNION ALL o UNION DISTINCT para conectarse.

Combate real:
use CTE recursivo para generar una secuencia de 1 a 10 en la línea de comando MySQL.

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

inserte la descripción de la imagen aquí

Las consultas CTE recursivas son muy convenientes para recorrer datos organizados y jerárquicos.
Combate real:
crea una tabla de datos de área t_area, que contiene información de provincias y ciudades.

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

inserte la descripción de la imagen aquí
Inserte datos de prueba en la tabla de datos t_area.

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

inserte la descripción de la imagen aquí
inserte la descripción de la imagen aquí
Use CTE recursivo para consultar la relación jerárquica en la tabla de datos t_area:

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;

inserte la descripción de la imagen aquí

Limitaciones de los CTE recursivos

La instrucción de consulta CTE recursiva debe contener una condición para detener la recursividad. Si no se establece una condición de detención, MySQL detendrá automáticamente la consulta e informará un error de acuerdo con la información de configuración. MySQL proporciona dos elementos de configuración por defecto para detener el CTE recursivo.

  • cte_max_recursion_ depth: al definir una consulta CTE recursiva, si no se establece una condición de terminación recursiva, MySQL generará un error cuando se alcance el número de ejecuciones establecido por el parámetro cte_max_recursion_ depth.
  • max_execution_time: max_execution_time es un parámetro utilizado para establecer el tiempo máximo de ejecución de la instrucción SQL en milisegundos. Cuando el tiempo de ejecución de la declaración SQL excede el valor establecido por este parámetro, MySQL arrojará un error.

Combate real: para el siguiente CTE recursivo que no establece la condición de finalización de la consulta, MySQL arrojará un mensaje de error y finalizará la consulta

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

ERROR 3636 (HY000): consulta recursiva cancelada después de 1001 iteraciones. Intente aumentar @@cte_max_recursion_ depth a un valor mayor.

El problema es: cuando no se establece una condición de finalización para la CTE recursiva, MySQL arrojará un mensaje de error en la consulta 1001 de forma predeterminada y finalizará la consulta.
inserte la descripción de la imagen aquí
Verifique el valor predeterminado del parámetro cte_max_recursion_ depth:
inserte la descripción de la imagen aquí
Por lo tanto: el valor predeterminado del parámetro cte_max_recursion_ depth es 1000, por lo que MySQL generará un error y finalizará la consulta de manera predeterminada en la consulta 1001.

Combate real: configuración max_execution_time
Establezca el parámetro cte_max_recursion_depth en un número grande

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

inserte la descripción de la imagen aquí
Vea el valor predeterminado del parámetro max_execution_time en MySQL:

SHOW VARIABLES LIKE 'max_execution%';

inserte la descripción de la imagen aquí
En MySQL, el valor del parámetro max_execution_time es milisegundos y el valor predeterminado es 0, lo que significa que no hay límite. Aquí, el valor de max_execution_time se establece en 1s en el nivel de sesión de MySQL.

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

inserte la descripción de la imagen aquí
Cuando el tiempo de ejecución de la instrucción SQL excede el valor establecido por max_execution_time, MySQL informa un error.

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

ERROR 3024 (HY000): se interrumpió la ejecución de la consulta, se excedió el tiempo máximo de ejecución de la instrucción

inserte la descripción de la imagen aquí
El mecanismo de terminación de recursividad predeterminado proporcionado por MySQL (elementos de configuración cte_max_recursion_ depth y max_execution_time) evita de forma eficaz el problema de la recursividad infinita.

Nota: De acuerdo con las necesidades reales, establezca explícitamente la condición para la terminación recursiva en la instrucción SQL de CTE. No confíe en el mecanismo predeterminado de MySQL para terminar la recursividad.

3. Resumen

Este artículo comparte qué es la consulta CTE, presenta CTE no recursivo y CTE recursivo, y presenta cómo usar CTE con ejemplos prácticos.
La consulta recursiva es un método de consulta basado en CTE, que se puede utilizar para procesar datos con estructura jerárquica, como estructura organizativa, estructura de árbol, etc. Las consultas recursivas implementan el recorrido de la jerarquía y la consulta al hacer referencia recursivamente a sí mismas.

Finalmente, el CTE recursivo limita los parámetros cte_max_recursion_depth y max_execution_time, a los que se debe prestar especial atención en el trabajo diario.

Entonces, um, la respuesta a esta pregunta es opcional. . Dígale al hermano Xu Zhu en voz alta en el área de comentarios.

4. Referencia

Árbol de habilidades avanzadas de MySQL: "Habilidades avanzadas de SQL:" CTE y consulta recursiva

Soy el hermano Xu Zhu, nos vemos mañana~

Supongo que te gusta

Origin blog.csdn.net/shi_hong_fei_hei/article/details/129910184
Recomendado
Clasificación