📜  MySQL公用表表达式(CTE)

📅  最后修改于: 2020-11-19 00:48:23             🧑  作者: Mango

MySQL公共表表达式(CTE)

在MySQL中,每个语句或查询都会产生一个临时结果或关系。通用表表达式或CTE用于命名该特定语句的执行范围内存在的那些临时结果集,例如CREATE,INSERT,SELECT,UPDATE,DELETE等。

与CTE相关的一些关键点是:

  • 它是使用WITH子句定义的。
  • WITH子句允许我们在单个查询中指定多个CTE。
  • 一个CTE可以引用属于同一WITH子句的其他CTE,但是这些CTE应该更早地定义。
  • CTE的执行范围存在于使用它的特定语句中。

MySQL CTE语法

MySQL CTE的语法包括名称,可选列列表以及定义公用表表达式(CTE)的语句/查询。定义CTE之后,我们可以将其用作SELECT,INSERT,UPDATE和DELETE查询中的视图。

以下是MySQL中CTE的基本语法:

WITH cte_name (column_names) AS (query) 
SELECT * FROM cte_name;

这是为了确保CTE参数中的列数必须与查询中的列数相同。如果我们尚未在CTE参数中定义列,它将使用定义CTE的查询列。

与派生表类似,它不能存储为对象,并且在执行完查询后将立即丢失。与派生表相比,CTE提供了更好的可读性,并且还提高了性能。

与派生表不同,CTE是可以使用自己的名称进行自我引用的子查询。它也称为递归CTE,也可以在同一查询中多次引用。

与递归CTE相关的一些要点是:

  • 它是使用WITH RECURSIVE子句定义的。
  • 递归CTE必须包含终止条件。
  • 我们将使用递归CTE进行系列生成和遍历层次结构或树结构数据。

MySQL递归CTE语法

以下是MySQL中递归CTE的基本语法:

WITH RECURSIVE cte_name (column_names) AS ( subquery ) 
SELECT * FROM cte_name;

在这里,子查询是一个MySQL查询,它使用cte_name作为自己的名称进行引用。

MySQL CTE示例

让我们使用各种示例来了解CTE在MySQL中的工作方式。在这里,我们将使用表“ employees”进行演示。假设此表包含以下数据:

执行以下语句以了解CTE的概念。在此示例中,CTE名称是employee_in_california,定义CTE的子查询返回emp_name,emp_age和city这三列。因此,CTE employee_in_california将返回位于加利福尼亚城市的所有雇员。

定义CTE employee_in_california后,我们在SELECT语句中引用了它,以仅选择位于加利福尼亚的那些雇员。

WITH employees_in_california AS (
    SELECT * FROM employees WHERE city = 'California' 
    ) 
    SELECT emp_name, emp_age, city FROM employees_in_california
    WHERE emp_age >= 32 ORDER BY emp_name;

执行以上语句后,将给出以下输出。在这里,我们可以看到结果仅返回位于加利福尼亚的员工数据。

更高级的MySQL CTE示例

假设我们有一个名为customer和order的表,其中包含以下数据:

表:客户

表:订单

请参阅以下使用INNER JOIN子句解释高级CTE示例的语句。

WITH total_customer_2020 AS (
    SELECT cust_id, name, occupation FROM customer 
    INNER JOIN orders USING (cust_id)
    ORDER BY age
)
SELECT * FROM orders JOIN total_customer_2020 USING (cust_id);

执行后,我们将得到如下输出:

MySQL递归CTE示例

以下示例说明了递归CTE的工作方式。考虑下面的语句,该语句生成一系列的前五个奇数:

WITH RECURSIVE 
odd_num_cte (id, n) AS
(
SELECT 1, 1 
union all
SELECT id+1, n+2 from odd_num_cte where id < 5 
)
SELECT * FROM odd_num_cte;

执行上面的语句后,将给出如下输出:

上面的语句包括两个部分,一个是非递归的,另一个是递归的。

非递归:SELECT 1、1

这部分将产生带有两列的初始行,分别为“ id”和“ n”,以及单行。

递归:从id_ 5的odd_num_cte中选择id + 1,n + 2

这部分负责将行添加到先前的输出,直到不满足终止条件(id <5)。当id达到5时,条件变为假,并且递归过程终止。

WITH子句使用

MySQL提供了许多上下文来使用WITH子句创建CTE。让我们详细讨论一下。

首先,我们可以在SELECT,UPDATE和DELETE查询的开头使用WITH子句,如下所示。

WITH ... SELECT ...
WITH ... UPDATE ...
WITH ... DELETE ...

其次,我们可以在子查询或派生表子查询的开头使用WITH子句,如下所示:

SELECT ... WHERE id IN (WITH ... SELECT ...);

SELECT * FROM (WITH ... SELECT ...) AS derived_table;

第三,我们可以在包含SELECT子句的SELECT语句的紧前面使用WITH子句,如下所示:

CREATE TABLE ... WITH ... SELECT ...
CREATE VIEW ... WITH ... SELECT ...
INSERT ... WITH ... SELECT ...
REPLACE ... WITH ... SELECT ...
DECLARE CURSOR ... WITH ... SELECT ...
EXPLAIN ... WITH ... SELECT ...

使用CTE的好处

  • 它提供了更好的查询可读性。
  • 它提高了查询的性能。
  • CTE允许我们将其用作VIEW概念的替代方案
  • 它也可以用作CTE的链接以简化查询。
  • 它也可以用来轻松实现递归查询。