MySQL——select_type详解——六月十五
select_type
:查询的类型。
SIMPLE
:简单 SELECT,不需要使用 UNION 操作或子查询。PRIMARY
:如果查询包含子查询,最外层的 SELECT 被标记为 PRIMARY。UNION
:UNION 操作中第二个或后面的 SELECT 语句。SUBQUERY
:子查询中的第一个 SELECT。DERIVED
:派生表的 SELECT 子查询。
可以用一种类比的方式来解释这些查询类型:
假设你是一位厨师,正在准备一道复杂的菜肴。你需要从不同的食材和调料中选择,并将它们组合在一起以制作最终的菜品。
-
SIMPLE
(简单)查询就像你从一个食材库中直接选择所需的食材,不需要进行任何额外的操作。 -
PRIMARY
(主要)查询是指你在制作菜品时需要使用到子菜品。你可能会先制作子菜品,然后将它们组合在一起形成最终的菜品。在查询中,最外层的 SELECT 语句就扮演了主要查询的角色。 -
UNION
(并集)查询是指你在制作菜品时需要将两个或多个独立的子菜品合并在一起。例如,你可能会制作一个蔬菜沙拉和一个水果沙拉,然后将它们合并成一个水果蔬菜沙拉。在查询中,UNION 操作中的第二个或后续的 SELECT 语句就扮演了并集查询的角色。 -
SUBQUERY
(子查询)是指你在制作菜品时需要使用到其他菜品的某些组成部分。例如,你可能需要先制作一种特殊的酱汁,然后将其用于主菜中。在查询中,子查询就像是你先制作某个组成部分,然后将其嵌入到主查询中的一部分。 -
DERIVED
(派生)查询是指你在制作菜品时需要使用到已经准备好的一些中间产品。例如,你可能需要制作一个蛋糕,但需要使用到已经制作好的奶油作为其中的一层。在查询中,派生查询就像是你从已经准备好的中间产品中提取所需的部分。
这种类比帮助理解不同类型的查询在查询过程中的作用和关系,就像在制作菜品时选择和组合不同的食材和调料一样。
提供一些示例,以更具体地说明各种查询类型的用途。
-
SIMPLE
(简单)查询示例:SELECT * FROM customers;
这是一个简单的 SELECT 查询,它从名为 “customers” 的表中选择所有的记录。
-
PRIMARY
(主要)查询示例:SELECT * FROM orders WHERE customer_id IN (SELECT id FROM customers WHERE country = 'USA');
这个查询中,外层的 SELECT 语句是主要查询,它使用了一个子查询来获取符合条件的客户 ID,然后根据这些客户 ID 查询相关的订单信息。
当我们具体考虑一个示例时,假设我们有两个表:orders
表和customers
表。
orders 表结构:
order_id | customer_id | order_date |
---|---|---|
1 | 1001 | 2023-06-01 |
2 | 1002 | 2023-06-02 |
3 | 1003 | 2023-06-03 |
4 | 1001 | 2023-06-04 |
5 | 1004 | 2023-06-05 |
customers 表结构:
customer_id | name | country |
---|---|---|
1001 | John | USA |
1002 | Emma | UK |
1003 | Mike | USA |
1004 | Sarah | Canada |
现在,我们可以使用以下查询来获取在美国的客户所下的所有订单:
SELECT * FROM orders WHERE customer_id IN (SELECT customer_id FROM customers WHERE country = 'USA');
这个查询的执行步骤如下:
-
子查询
(SELECT customer_id FROM customers WHERE country = 'USA')
将返回在美国的客户的customer_id
值,即1001
和1003
。 -
外部查询
SELECT * FROM orders WHERE customer_id IN (...)
将在orders
表中查找具有这些customer_id
值的订单。
查询结果将是在美国的客户所下的所有订单:
order_id | customer_id | order_date |
---|---|---|
1 | 1001 | 2023-06-01 |
3 | 1003 | 2023-06-03 |
4 | 1001 | 2023-06-04 |
这样,我们就通过使用 customer_id IN (SELECT ...)
条件,成功地筛选出了在美国的客户所下的订单。
UNION
(并集)查询示例:
这个查询使用 UNION 操作将两个独立的 SELECT 语句的结果合并在一起,获取属于水果或蔬菜类别的产品名称。SELECT product_name FROM products WHERE category = 'Fruits'UNIONSELECT product_name FROM products WHERE category = 'Vegetables';
我很抱歉,在之前的回答中有误导性的陈述。实际上,上述查询未显示如何消除重复项。如果查询结果中存在重复的产品名称,它们将全部显示出来。
假设我们有以下产品表:
products 表结构:
product_id | product_name | category |
---|---|---|
1 | Apple | Fruits |
2 | Banana | Fruits |
3 | Carrot | Vegetables |
4 | Tomato | Vegetables |
5 | Apple | Fruits |
现在,我们将使用以下查询来获取属于水果或蔬菜类别的产品名称,并消除重复项:
SELECT product_name FROM products WHERE category = 'Fruits'UNION DISTINCTSELECT product_name FROM products WHERE category = 'Vegetables';
这个查询的执行步骤如下:
-
第一个查询
SELECT product_name FROM products WHERE category = 'Fruits'
选择了类别为 “Fruits” 的产品名称。这将返回 “Apple”、“Banana” 和 “Apple”。 -
第二个查询
SELECT product_name FROM products WHERE category = 'Vegetables'
选择了类别为 “Vegetables” 的产品名称。这将返回 “Carrot” 和 “Tomato”。 -
UNION DISTINCT
操作将两个查询结果合并在一起,并自动去除重复的产品名称。
最终的查询结果将是属于水果或蔬菜类别的产品名称,并消除重复项:
product_name |
---|
Apple |
Banana |
Carrot |
Tomato |
请注意,现在结果集中只有一个 “Apple”,即使在原始数据中有两个相同的产品名称。通过使用 UNION DISTINCT
,我们成功地消除了重复项,确保了每个产品名称只出现一次。
SUBQUERY
(子查询)示例:
这个查询中,子查询首先获取部门名称为 “HR” 的部门 ID,然后外层的 SELECT 语句根据该部门 ID 获取相应的员工信息。SELECT * FROM employees WHERE department_id = (SELECT id FROM departments WHERE name = 'HR');
假设我们有两个表:employees
表和departments
表,用于存储员工和部门的信息。
employees 表结构:
employee_id | employee_name | department_id |
---|---|---|
1 | John | 1 |
2 | Emma | 2 |
3 | Mike | 1 |
4 | Sarah | 3 |
5 | David | 2 |
departments 表结构:
department_id | department_name |
---|---|
1 | HR |
2 | Sales |
3 | IT |
现在,我们可以使用以下查询来获取部门名称为 “HR” 的所有员工信息:
SELECT * FROM employees WHERE department_id = (SELECT department_id FROM departments WHERE department_name = 'HR');
这个查询的执行步骤如下:
-
子查询
(SELECT department_id FROM departments WHERE department_name = 'HR')
将返回部门名称为 “HR” 的部门ID,即1
。 -
外部查询
SELECT * FROM employees WHERE department_id = (...)
将在employees
表中查找部门ID为1
的员工。
查询结果将是部门名称为 “HR” 的所有员工信息:
employee_id | employee_name | department_id |
---|---|---|
1 | John | 1 |
3 | Mike | 1 |
这样,我们就通过使用子查询来获取部门名称为 “HR” 的部门ID,并将其用作外部查询的条件,成功地筛选出了部门为 “HR” 的所有员工信息。
DERIVED
(派生)查询示例:
这个查询中,派生查询创建了一个临时表SELECT product_name, price FROM (SELECT * FROM products WHERE category = 'Bakery') AS bakery_products;
bakery_products
,它包含了所有属于 “Bakery” 类别的产品。然后外层的 SELECT 语句从这个临时表中选择产品名称和价格。
假设我们有一个名为 products
的表,用于存储各种产品的信息。
products 表结构:
product_id | product_name | category | price |
---|---|---|---|
1 | Bread | Bakery | 2.99 |
2 | Cake | Bakery | 9.99 |
3 | Cookie | Snacks | 1.49 |
4 | Muffin | Bakery | 1.99 |
5 | Donut | Bakery | 0.99 |
现在,我们可以使用以下查询来选择类别为 “Bakery” 的产品的名称和价格:
SELECT product_name, price FROM (SELECT * FROM products WHERE category = 'Bakery') AS bakery_products;
这个查询的执行步骤如下:
-
子查询
(SELECT * FROM products WHERE category = 'Bakery') AS bakery_products
选择了类别为 “Bakery” 的所有产品。 -
外部查询
SELECT product_name, price FROM (...)
在子查询返回的结果上进行查询,选择了产品名称和价格列。
最终的查询结果将是类别为 “Bakery” 的产品的名称和价格:
product_name | price |
---|---|
Bread | 2.99 |
Cake | 9.99 |
Muffin | 1.99 |
Donut | 0.99 |
通过将子查询的结果作为临时表命名为 bakery_products
,然后在外部查询中选择所需的列,我们成功地筛选出了类别为 “Bakery” 的产品的名称和价格。
如果没有在子查询后面使用 AS bakery_products
进行别名定义,查询仍然可以正常执行,但在后续的查询中无法引用子查询结果作为临时表。
以下是没有使用别名的示例查询:
SELECT product_name, price FROM (SELECT * FROM products WHERE category = 'Bakery');
该查询的执行步骤如下:
-
子查询
(SELECT * FROM products WHERE category = 'Bakery')
选择了类别为 “Bakery” 的所有产品。 -
外部查询
SELECT product_name, price FROM (...)
在子查询返回的结果上进行查询,选择了产品名称和价格列。
虽然查询本身没有错误,但由于没有为子查询结果指定别名,后续无法直接引用该子查询的结果。在这种情况下,如果我们尝试在外部查询或其他查询中引用该子查询的结果,将会出现语法错误。
因此,使用别名可以将子查询结果命名为一个临时表,使我们可以在后续的查询中引用该临时表。这种方式有助于提高查询的可读性和灵活性。
来源地址:https://blog.csdn.net/qq_59344127/article/details/131234613
免责声明:
① 本站未注明“稿件来源”的信息均来自网络整理。其文字、图片和音视频稿件的所属权归原作者所有。本站收集整理出于非商业性的教育和科研之目的,并不意味着本站赞同其观点或证实其内容的真实性。仅作为临时的测试数据,供内部测试之用。本站并未授权任何人以任何方式主动获取本站任何信息。
② 本站未注明“稿件来源”的临时测试数据将在测试完成后最终做删除处理。有问题或投稿请发送至: 邮箱/279061341@qq.com QQ/279061341