文章目录
- SQL语句进阶版
- MySQL查询数据的过程
- 一、连接与身份验证
- 二、查询缓存(MySQL 8.0之前版本)
- 三、查询解析与优化
- 四、查询执行
- 五、返回结果
- MySQL语句
- 准备环境
- 创建 `location` 表并插入数据
- 创建 `store_info` 表并插入数据
- 查询示例
- 语句示例
- SELECT
- DISTINCT
- WHERE
- AND OR
- IN
- BETWEEN
- 通配符
- LIKE
- ORDER BY
- 函数
- 数学函数
- 聚合函数
- 字符串函数
- GROUP BY
- HAVING
- 别名
- 子查询
- EXISTS
- 连接查询
- 内连接(INNER JOIN)
- 左连接(LEFT JOIN)
- 右连接(RIGHT JOIN)
- 使用聚合函数和内连接的示例
- 视图(View)详解
- 视图的基本概念
- 视图与表的区别
- 视图的用途
- 视图的创建与删除
- 注意事项
- UNION 和 UNION ALL 详细讲解
- UNION 操作符
- UNION ALL 操作符
- 注意事项
- 交集值
- 1. 使用`INNER JOIN`获取交集值
- 2. 使用`USING`子句简化`INNER JOIN`
- 3. 使用`DISTINCT`确保结果无重复
- 4. 使用`IN`子句获取交集值
- 5. 使用`LEFT JOIN`和`IS NOT NULL`条件获取交集值
- 6. 使用子查询和`GROUP BY`
- 7. 使用`UNION ALL`和`HAVING`条件获取交集值
- 差集值
- 总结
- CASE 表达式
- 语法一:简单CASE表达式
- 语法二:搜索CASE表达式
- 示例
- 空值(`NULL`)和无值(空字符串`''`)的区别
- SQL正则表达
- 存储过程
- 存储过程的优点
- 创建存储过程
- 调用存储过程
- 查看存储过程
- 存储过程的参数
- 示例
- 删除存储过程
- 存储过程的控制语句
- 调用存储过程
- 问答环节+简要总结
SQL语句进阶版
MySQL查询数据的过程
一、连接与身份验证
- 客户端请求:客户端(如应用程序、数据库管理工具等)向MySQL服务器发送一条查询请求。
-
连接器处理:MySQL的连接器(Connector)负责处理这个连接请求。连接器是连接客户端和MySQL服务器的一个重要组件,其主要功能是处理连接请求、验证客户端身份、协商客户端和服务器之间的协议等。
- 连接池管理:在高并发情况下,连接池管理器会预先创建一定数量的连接,以便客户端能够快速地获取可用的连接。当客户端请求连接时,连接池管理器会检查连接池中是否有空闲连接,如果有,则将其提供给客户端;如果没有,则会创建新的连接。
- 身份验证:连接器会验证客户端提供的用户名、密码等身份信息,以确保客户端具有访问MySQL服务器的权限。
- 权限控制:在身份验证通过后,MySQL还会检查客户端是否具有执行该查询的权限。这通常涉及查询对象的权限验证,如数据表、数据列的访问权限等。
二、查询缓存(MySQL 8.0之前版本)
注意:在MySQL 8.0版本中,查询缓存已被删除,因此以下步骤仅适用于MySQL 8.0之前的版本。
- 检查缓存:MySQL会首先检查查询缓存,看是否有之前执行过的相同查询及其结果。这是通过哈希查找来实现的,哈希查找只能进行全值查找(即SQL语句必须完全一致)。
- 缓存命中:如果缓存命中,MySQL会立即返回存储在缓存中的结果,而无需进行后续的解析、优化和执行步骤。这可以大大提高查询性能。
- 缓存未命中:如果缓存未命中,MySQL则会进入后续的查询解析、优化和执行步骤。
三、查询解析与优化
-
查询解析:
- 语法解析:MySQL解析器通过关键字将SQL语句进行解析,并生成对应的解析树。解析器会使用MySQL语法规则验证和解析查询,如验证是否使用了错误的关键字、关键字的顺序是否正确、引号是否前后匹配等。
- 预处理:预处理器会根据一些MySQL规则进一步检查解析树是否合法。例如,检查数据表和数据列是否存在、解析名字和别名是否有歧义等。同时,预处理器还会验证用户权限。
-
查询优化:
- 优化器作用:优化器的目的是找到最好的执行计划。一条查询可以有多种执行方式,但最终都会返回相同的结果。优化器的作用就是选择其中成本最小的一种执行方式。
- 生成执行计划:优化器会将MySQL语句转换为执行计划。这个执行计划表明了应该使用哪些索引执行查询、表之间的连接顺序等。MySQL使用基于成本的优化器(CBO),会预测一个查询使用某种执行计划的成本,并选择成本最小的一个。
四、查询执行
- 调用存储引擎:MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询。存储引擎是MySQL中负责存取真实数据的组件,它接收上层传下来的指令,对表中的数据进行读取或写入操作。
- 执行过程:查询执行引擎根据执行计划来完成整个查询。执行计划是一个数据结构(指令树),MySQL会根据执行计划给出的指令逐步执行。在执行过程中,有大量的操作需要调用存储引擎实现的接口来完成,这些接口即为“handler API”。
五、返回结果
- 结果返回:MySQL将查询结果集返回给客户端。这是一个增量逐步返回的过程,即当查询生成第一条结果时,MySQL就可以开始向客户端逐步返回结果了。这样可以节省服务端内存,并让客户端第一时间获得返回结果。
- 缓存查询结果(MySQL 8.0之前版本):如果查询可以被缓存(在MySQL 8.0之前的版本中),MySQL会在这个阶段将结果存放到查询缓存中,以便后续相同查询可以直接从缓存中获取结果。但在MySQL 8.0及之后的版本中,由于查询缓存已被删除,因此不会再进行这一步操作。
MySQL语句
准备环境
创建 location
表并插入数据
-- 创建 location 表
create table location (
Region char(20),
Store_Name char(20)
);
-- 插入数据到 location 表
insert into location values('East','Boston');
insert into location values('East','New York');
insert into location values('West','Los Angeles');
insert into location values('West','Houston');
-- location 表格
+----------+--------------+
| Region | Store_Name |
|----------+--------------|
| East | Boston |
| East | New York |
| West | Los Angeles |
| West | Houston |
+----------+--------------+
创建 store_info
表并插入数据
-- 创建 store_info 表
create table store_info (
Store_Name char(20),
Sales int(10),
Date char(10)
);
-- 插入数据到 store_info 表
insert into store_info values('Los Angeles','1500','2020-12-05');
insert into store_info values('Houston','250','2020-12-07');
insert into store_info values('Los Angeles','300','2020-12-08');
insert into store_info values('Boston','700','2020-12-08');
insert into store_info values('Washington','1000','2020-12-09');
insert into store_info values('Chicago','800','2020-12-10');
-- store_info 表格
+--------------+---------+------------+
| Store_Name | Sales | Date |
|--------------+---------+------------|
| Los Angeles | 1500 | 2020-12-05 |
| Houston | 250 | 2020-12-07 |
| Los Angeles | 300 | 2020-12-08 |
| Boston | 700 | 2020-12-08 |
| Washington | 1000 | 2020-12-09 |
| Chicago | 800 | 2020-12-10 |
+--------------+---------+------------+
查询示例
-- 查询每个地区的总销售额
select l.Region, sum(s.Sales) as Total_Sales
from location l
join store_info s on l.Store_Name = s.Store_Name
group by l.Region;
-- 结果
+--------+------------+
| Region | Total_Sales|
+--------+------------+
| East | 1400 |
| West | 2050 |
+--------+------------+
您已经列出了SQL查询中一些非常基础且重要的部分,包括SELECT
语句、DISTINCT
关键字、WHERE
子句、逻辑运算符(AND
和OR
)、IN
操作符、BETWEEN
操作符以及通配符的使用。下面我将对每部分进行更详细的讲解:
语句示例
SELECT
SELECT
语句用于从数据库表中检索数据。您可以指定要检索的字段,或者使用*
来选择所有字段。
示例:
SELECT Store_Name FROM store_info; -- 仅选择Store_Name字段
SELECT * FROM store_info; -- 选择所有字段
DISTINCT
DISTINCT
关键字用于返回唯一不同的值。它通常与SELECT
语句一起使用,以消除结果集中的重复行。
示例:
SELECT DISTINCT Store_Name FROM store_info; -- 仅返回不重复的Store_Name
WHERE
WHERE
子句用于过滤记录,只返回满足指定条件的记录。
示例:
SELECT Store_Name FROM store_info WHERE Sales > 1000; -- 返回Sales大于1000的Store_Name
AND OR
AND
和OR
是逻辑运算符,用于在WHERE
子句中组合多个条件。AND
要求所有条件都为真,而OR
要求至少有一个条件为真。
示例:
SELECT Store_Name FROM store_info WHERE Sales > 1000 OR (Sales < 500 AND Sales > 200); -- 返回Sales大于1000或(Sales小于500且大于200)的Store_Name
注意:在给出的示例中,条件(Sales < 500 AND Sales > 200)
实际上是一个不可能的情况,因为没有一个数字能同时小于500且大于200。这里可能是为了演示逻辑运算符的用法而给出的示例。
IN
IN
操作符允许您指定多个可能的值,返回字段值等于这些值之一的记录。
示例:
SELECT * FROM store_info WHERE Store_Name IN ('Los Angeles', 'Houston'); -- 返回Store_Name为'Los Angeles'或'Houston'的记录
BETWEEN
BETWEEN
操作符用于选取在某个范围内的值,范围包括边界值。
示例:
SELECT * FROM store_info WHERE Date BETWEEN '2020-12-06' AND '2020-12-10'; -- 返回Date在'2020-12-06'和'2020-12-10'之间的记录
通配符
通配符通常与LIKE
操作符一起使用,用于在WHERE
子句中搜索列中的特定模式。
-
%
:代表零个、一个或多个字符。 -
_
:代表单个字符。
示例:
SELECT * FROM store_info WHERE Store_Name LIKE 'L%'; -- 返回Store_Name以'L'开头的所有记录
SELECT * FROM store_info WHERE Store_Name LIKE '_os%'; -- 返回Store_Name第二个字符为'o',且以's'后跟任意字符结尾的所有记录
使用通配符进行搜索时,请注意性能问题,因为通配符搜索通常比精确匹配搜索更耗时,特别是在大型数据集上。如果可能的话,考虑使用索引和全文搜索来提高性能。'A_Z'
:所有以 ‘A’ 起头,另一个任何值的字符,且以 ‘Z’ 为结尾的字符串。例如,‘ABZ’ 和 ‘A2Z’ 都符合这一个模式,而 ‘AKKZ’ 并不符合 (因为在 A 和 Z 之间有两个字符,而不是一个字符)。'ABC%
': 所有以 ‘ABC’ 起头的字符串。例如,‘ABCD’ 和 ‘ABCABC’ 都符合这个模式。'%XYZ'
: 所有以 ‘XYZ’ 结尾的字符串。例如,‘WXYZ’ 和 ‘ZZXYZ’ 都符合这个模式。'%AN%'
: 所有含有 'AN’这个模式的字符串。例如,‘LOS ANGELES’ 和 ‘SAN FRANCISCO’ 都符合这个模式。'_AN%'
:所有第二个字母为 ‘A’ 和第三个字母为 ‘N’ 的字符串。例如,‘SAN FRANCISCO’ 符合这个模式,而 ‘LOS ANGELES’ 则不符合这个模式。
LIKE
LIKE
操作符用于在WHERE
子句中搜索列中的特定模式。它通常与通配符(如%
和_
)一起使用。
示例:
SELECT * FROM store_info WHERE Store_Name LIKE '%os%'; -- 返回Store_Name中包含'os'的所有记录
ORDER BY
ORDER BY
子句用于对结果集进行排序。您可以按一个或多个列进行排序,并指定升序(ASC
,默认)或降序(DESC
)。
示例:
SELECT Store_Name, Sales, Date FROM store_info ORDER BY Sales DESC; -- 按Sales降序排序
函数
数学函数
数学函数用于执行数值计算。
-
abs(x)
: 返回x的绝对值。 -
rand()
: 返回0到1之间的随机数。 -
mod(x, y)
: 返回x除以y的余数。 -
power(x, y)
: 返回x的y次方。 -
sqrt(x)
: 返回x的平方根。 -
round(x)
: 返回离x最近的整数。 -
round(x, y)
: 返回x保留y位小数四舍五入后的值。 -
truncate(x, y)
: 返回x截断为y位小数的值,不进行四舍五入。 -
ceil(x)
: 返回大于或等于x的最小整数。 -
floor(x)
: 返回小于或等于x的最大整数。 -
greatest(x1, x2, ...)
: 返回集合中的最大值。 -
least(x1, x2, ...)
: 返回集合中的最小值。
示例:
SELECT abs(-1), rand(), mod(5, 3), power(2, 3), round(1.89);
-- 返回: 1, (随机数), 2, 8, 2
SELECT round(1.8937, 3), truncate(1.235, 2), ceil(5.2), floor(2.1), least(1.89, 3, 6.1, 2.1);
-- 返回: 1.894, 1.23, 6, 2, 1.89
聚合函数
聚合函数用于计算一组值的统计信息。
-
avg(x)
: 返回x的平均值。 -
count(x)
: 返回x中非NULL值的个数。count(*)
返回所有行的个数。 -
min(x)
: 返回x的最小值。 -
max(x)
: 返回x的最大值。 -
sum(x)
: 返回x的总和。
示例:
SELECT avg(Sales) FROM store_info; -- 返回Sales的平均值
SELECT count(Store_Name) FROM store_info; -- 返回Store_Name中非NULL值的个数
SELECT count(*) FROM City; -- 返回City表中所有行的个数
SELECT max(Sales) FROM store_info; -- 返回Sales的最大值
SELECT sum(Sales) FROM store_info; -- 返回Sales的总和
字符串函数
字符串函数用于操作字符串数据。
-
concat(x, y)
: 将x和y拼接成一个字符串。 -
substr(x, y)
: 从字符串x的第y个位置开始获取子字符串(注意:在某些数据库中,索引可能从1开始,也可能从0开始,这取决于具体的数据库系统)。 -
substr(x, y, z)
: 从字符串x的第y个位置开始获取长度为z的子字符串。 -
length(x)
: 返回字符串x的长度。 -
replace(x, y, z)
: 将字符串x中的y替换为z。 -
trim()
: 返回去除指定格式(如空格)的值。可以指定从字符串的起头、结尾或起头及结尾移除的字符。 -
upper(x)
: 将字符串x转换为大写。 -
lower(x)
: 将字符串x转换为小写。 -
left(x, y)
: 返回字符串x的前y个字符。 -
right(x, y)
: 返回字符串x的后y个字符。 -
repeat(x, y)
: 将字符串x重复y次。 -
space(x)
: 返回x个空格组成的字符串。 -
strcmp(x, y)
: 比较x和y,返回-1(x<y)、0(x=y)或1(x>y)。 -
reverse(x)
: 将字符串x反转。
示例:
SELECT concat(Region, ' ', Store_Name) FROM location WHERE Store_Name = 'Boston';
-- 假设Region为'East',则返回'East Boston'
SELECT substr('Hello World', 7);
-- 返回'World'(假设索引从1开始)
SELECT TRIM(LEADING 'New ' FROM 'New York');
-- 返回'York'
SELECT REPLACE('Hello World', 'World', 'SQL');
-- 返回'Hello SQL'
注意:
- 在使用
substr
函数时,请注意不同数据库系统中字符串索引的起始值可能不同(从0或1开始)。 -
TRIM
函数的语法可能因数据库系统而异。上述示例中的语法是通用的,但具体实现可能需要根据您使用的数据库系统进行调整。 - 在执行SQL查询之前,请确保您已经正确连接到了数据库,并且表名和列名与您的数据库架构相匹配。
- 以下是对您提供的SQL查询相关内容的整理,包括GROUP BY、HAVING、别名、子查询、EXISTS以及连接查询的详细解释和示例。
GROUP BY
GROUP BY用于对查询结果进行分组,通常与聚合函数(如SUM、COUNT、AVG等)一起使用。其原则如下:
- 在GROUP BY后面出现的字段,必须在SELECT后面出现。
- 在SELECT后面出现且未在聚合函数中使用的字段,必须出现在GROUP BY后面。
示例:
SELECT Store_Name, SUM(Sales) AS TotalSales FROM store_info GROUP BY Store_Name ORDER BY TotalSales DESC;
HAVING
HAVING用于过滤GROUP BY语句返回的记录集,通常与GROUP BY一起使用。它允许使用聚合函数作为过滤条件,这是WHERE子句所不具备的。
示例:
SELECT Store_Name, SUM(Sales) AS TotalSales FROM store_info GROUP BY Store_Name HAVING SUM(Sales) > 1500;
WHERE与HAVING之间的区别?
WHERE
- 作用:
WHERE
子句用于在数据被分组或聚合之前过滤行。- 适用场景: 通常用于基于单行的条件来过滤数据。例如,选择特定列的值满足某个条件的行。
- 数据类型: 可以使用各种条件表达式,如比较运算符(=、<、>、<>、<=、>=)、逻辑运算符(AND、OR、NOT)等。
- 执行顺序: 在
GROUP BY
之前执行。
示例:SELECT * FROM employees WHERE age > 30;
这个查询会选择所有年龄大于30的员工。
HAVING
- 作用:
HAVING
子句用于在数据被分组和聚合之后过滤组。- 适用场景: 通常用于基于聚合函数(如SUM、AVG、COUNT、MAX、MIN)的结果来过滤组。
- 数据类型: 通常与聚合函数一起使用,并且可以使用比较运算符和逻辑运算符。
- 执行顺序: 在
GROUP BY
之后执行。
示例:SELECT department, COUNT(*) AS num_employees FROM employees GROUP BY department HAVING COUNT(*) > 10;
这个查询会选择员工数量大于10的部门。
总结
WHERE
用于在数据分组前过滤行。HAVING
用于在数据分组和聚合后过滤组。注意
WHERE
子句不能包含聚合函数,而HAVING
子句则可以。HAVING
通常与GROUP BY
一起使用,而WHERE
不一定需要GROUP BY
。
别名
别名分为字段别名和表格别名,用于简化查询结果或提高可读性。
字段别名示例:
SELECT Store_Name AS Store, SUM(Sales) AS TotalSales FROM store_info;
表格别名示例:
SELECT A.Store_Name, SUM(A.Sales) AS TotalSales FROM store_info AS A GROUP BY A.Store_Name;
子查询
子查询是在另一个SQL查询中嵌套另一个SQL查询。子查询可以出现在WHERE子句或HAVING子句中。
示例:
SELECT SUM(Sales) FROM store_info WHERE Store_Name IN (SELECT Store_Name FROM location WHERE Region = 'West');
EXISTS
EXISTS用于检查子查询是否返回任何结果。如果子查询返回至少一行结果,则外部查询的结果将包含该行。
示例:
SELECT * FROM store_info A WHERE EXISTS (SELECT 1 FROM location B WHERE B.Store_Name = A.Store_Name);
连接查询
连接查询用于从多个表中检索数据。常见的连接类型包括内连接(INNER JOIN)、左连接(LEFT JOIN)和右连接(RIGHT JOIN)。
连接查询用于从多个表中检索相关数据。在关系型数据库中,数据通常分布在多个表中,每个表包含特定的信息。连接查询通过联结字段(通常是主键和外键)将这些表关联起来,从而允许用户在一个查询中从多个表中获取数据。
内连接(INNER JOIN)
内连接只返回两个表中联结字段相等的行。如果联结字段在两个表中不匹配,则这些行不会出现在结果集中。
示例:
SELECT * FROM location A INNER JOIN store_info B ON A.Store_Name = B.Store_Name;
这条语句从location
和store_info
两个表中检索数据,只返回那些Store_Name
字段值在两个表中都存在的行。
另外,内连接还可以使用WHERE子句来实现,而不是使用INNER JOIN语法:
SELECT * FROM location A, store_info B WHERE A.Store_Name = B.Store_Name;
这条语句与上面的INNER JOIN语句等效。
左连接(LEFT JOIN)
左连接返回包括左表(位于JOIN操作左侧的表)中的所有记录和右表中联结字段相等的记录。如果右表中没有与左表匹配的行,则结果集中的这些行将包含NULL值。
示例:
SELECT * FROM location A LEFT JOIN store_info B ON A.Store_Name = B.Store_Name;
这条语句从location
表中检索所有行,并尝试将它们与store_info
表中的行匹配。如果store_info
表中没有与location
表中的Store_Name
匹配的行,则结果集中的这些store_info
表的列将包含NULL值。
右连接(RIGHT JOIN)
右连接与左连接类似,但它返回的是右表(位于JOIN操作右侧的表)中的所有记录和左表中联结字段相等的记录。
示例:
SELECT * FROM location A RIGHT JOIN store_info B ON A.Store_Name = B.Store_Name;
这条语句从store_info
表中检索所有行,并尝试将它们与location
表中的行匹配。如果location
表中没有与store_info
表中的Store_Name
匹配的行,则结果集中的这些location
表的列将包含NULL值。
使用聚合函数和内连接的示例
SELECT A.Region AS REGION, SUM(B.Sales) AS SALES
FROM location A
INNER JOIN store_info B ON A.Store_Name = B.Store_Name
GROUP BY A.Region;
这条语句首先使用内连接从location
和store_info
两个表中检索数据,只返回那些Store_Name
字段值在两个表中都存在的行。然后,它使用GROUP BY子句按location
表中的Region
字段对结果进行分组。最后,它使用SUM函数计算每个区域的总销售额,并将结果集中的列重命名为REGION
和SALES
。
视图(View)详解
视图的基本概念
视图(View)是数据库中的一种虚拟表,它并不存储实际的数据,而是存储了一个查询的定义。当你查询视图时,数据库会根据视图的定义动态地生成结果集,就像查询一个实际的表一样。视图的主要作用是简化复杂查询、提高查询的可读性和安全性。
视图与表的区别
- 数据存储:表是存储数据的实际结构,而视图不存储数据,只存储查询的定义。
- 更新操作:虽然视图可以像表一样进行查询操作,但并非所有的视图都支持更新操作(如插入、更新、删除)。这取决于视图的定义是否允许这些操作。
- 持久性:表是持久存储数据的结构,而视图在数据库中是持久的定义,但不像临时表那样在用户会话结束后消失。
视图的用途
- 简化复杂查询:通过视图,可以将复杂的查询逻辑封装起来,使得用户可以通过简单的查询语句获取所需的数据。
- 数据抽象:视图提供了一种从底层数据表中抽象出数据的方式,使得用户无需关心底层表的结构和复杂性。
- 安全性:通过视图,可以限制用户对数据的访问权限,只暴露给用户需要的数据,提高数据的安全性。
视图的创建与删除
-
创建视图:使用
CREATE VIEW
语句创建视图。语法如下:
例如,创建一个名为CREATE VIEW "视图表名" AS "SELECT 语句";
V_REGION_SALES
的视图,该视图显示每个地区的销售总额:CREATE VIEW V_REGION_SALES AS SELECT A.Region AS REGION, SUM(B.Sales) AS SALES FROM location A INNER JOIN store_info B ON A.Store_Name = B.Store_Name GROUP BY A.Region;
-
查询视图:创建视图后,可以使用
SELECT
语句查询视图,就像查询一个实际的表一样:SELECT * FROM V_REGION_SALES;
-
删除视图:使用
DROP VIEW
语句删除视图。语法如下:
例如,删除DROP VIEW "视图表名";
V_REGION_SALES
视图:DROP VIEW V_REGION_SALES;
注意事项
- 性能:虽然视图可以简化查询,但在某些情况下,使用视图可能会降低查询性能,因为每次查询视图时,数据库都需要执行视图定义中的查询。
- 更新限制:并非所有的视图都支持更新操作。如果视图涉及多表连接、聚合函数、子查询等复杂操作,那么视图可能不支持更新。
- 权限管理:通过视图,可以精细地控制用户对数据的访问权限,提高数据的安全性。
视图是数据库中的一种强大工具,通过它可以简化复杂查询、提高查询的可读性和安全性。但在使用视图时,也需要注意其可能带来的性能问题和更新限制。
UNION 和 UNION ALL 详细讲解
UNION 操作符
UNION
操作符用于合并两个或多个 SELECT
语句的结果集。这些 SELECT
语句必须返回相同数量的列,并且这些列的数据类型必须兼容。UNION
操作符会自动去除结果集中的重复行。
语法:
[SELECT 语句 1] UNION [SELECT 语句 2];
示例:
SELECT Store_Name FROM location
UNION
SELECT Store_Name FROM store_info;
在这个例子中,UNION
操作符合并了 location
表和 store_info
表中 Store_Name
列的结果集,并去除了重复的商店名称。
UNION ALL 操作符
UNION ALL
操作符与 UNION
类似,也用于合并两个或多个 SELECT
语句的结果集。但是,UNION ALL
不会去除结果集中的重复行。
语法:
[SELECT 语句 1] UNION ALL [SELECT 语句 2];
示例:
SELECT Store_Name FROM location
UNION ALL
SELECT Store_Name FROM store_info;
- 使用
UNION
的示例中,假设location
表和store_info
表中有一些相同的Store_Name
值,这些值在最终的结果集中只会出现一次。 - 使用
UNION ALL
的示例中,假设location
表和store_info
表中有一些相同的Store_Name
值,这些值在最终的结果集中会出现多次,每次出现都表示它们分别来自哪个表。
在这个例子中,UNION ALL
操作符合并了 location
表和 store_info
表中 Store_Name
列的结果集,并保留了所有重复的商店名称。
注意事项
-
列数和数据类型:使用
UNION
或UNION ALL
时,每个SELECT
语句必须返回相同数量的列,并且这些列的数据类型必须兼容。 -
排序:默认情况下,
UNION
和UNION ALL
操作符的结果集是按照列的顺序进行排序的,但这并不意味着结果集是按照某个特定的列排序的。如果需要排序,可以使用ORDER BY
子句。 -
性能:
UNION ALL
通常比UNION
更快,因为UNION
需要执行额外的步骤来去除重复行。 -
NULL 值:在
UNION
或UNION ALL
的结果集中,NULL
值被视为相同的值。因此,如果两个SELECT
语句的结果集中都有NULL
值,这些NULL
值在UNION
的结果集中只会出现一次(除非使用UNION ALL
)。
交集值
1. 使用INNER JOIN
获取交集值
SELECT A.Store_Name
FROM location A
INNER JOIN store_info B
ON A.Store_Name = B.Store_Name;
这个查询通过INNER JOIN
连接location
和store_info
两个表,并基于Store_Name
字段匹配记录。只有当两个表中都存在相同的Store_Name
时,该名称才会出现在结果集中。
2. 使用USING
子句简化INNER JOIN
SELECT A.Store_Name
FROM location A
INNER JOIN store_info B
USING(Store_Name);
这个查询与上一个查询功能相同,但USING
子句简化了连接条件,因为它自动知道要基于哪个字段(在本例中是Store_Name
)进行连接。
3. 使用DISTINCT
确保结果无重复
SELECT DISTINCT A.Store_Name
FROM location A
INNE