【MySQL数据库】MySQL高级语句(SQL语句进阶版)

时间:2024-10-19 13:50:11

文章目录

  • 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查询数据的过程

一、连接与身份验证

  1. 客户端请求:客户端(如应用程序、数据库管理工具等)向MySQL服务器发送一条查询请求。
  2. 连接器处理:MySQL的连接器(Connector)负责处理这个连接请求。连接器是连接客户端和MySQL服务器的一个重要组件,其主要功能是处理连接请求、验证客户端身份、协商客户端和服务器之间的协议等。
    • 连接池管理:在高并发情况下,连接池管理器会预先创建一定数量的连接,以便客户端能够快速地获取可用的连接。当客户端请求连接时,连接池管理器会检查连接池中是否有空闲连接,如果有,则将其提供给客户端;如果没有,则会创建新的连接。
    • 身份验证:连接器会验证客户端提供的用户名、密码等身份信息,以确保客户端具有访问MySQL服务器的权限。
  3. 权限控制:在身份验证通过后,MySQL还会检查客户端是否具有执行该查询的权限。这通常涉及查询对象的权限验证,如数据表、数据列的访问权限等。

二、查询缓存(MySQL 8.0之前版本)

注意:在MySQL 8.0版本中,查询缓存已被删除,因此以下步骤仅适用于MySQL 8.0之前的版本。

  1. 检查缓存:MySQL会首先检查查询缓存,看是否有之前执行过的相同查询及其结果。这是通过哈希查找来实现的,哈希查找只能进行全值查找(即SQL语句必须完全一致)。
  2. 缓存命中:如果缓存命中,MySQL会立即返回存储在缓存中的结果,而无需进行后续的解析、优化和执行步骤。这可以大大提高查询性能。
  3. 缓存未命中:如果缓存未命中,MySQL则会进入后续的查询解析、优化和执行步骤。

三、查询解析与优化

  1. 查询解析
    • 语法解析:MySQL解析器通过关键字将SQL语句进行解析,并生成对应的解析树。解析器会使用MySQL语法规则验证和解析查询,如验证是否使用了错误的关键字、关键字的顺序是否正确、引号是否前后匹配等。
    • 预处理:预处理器会根据一些MySQL规则进一步检查解析树是否合法。例如,检查数据表和数据列是否存在、解析名字和别名是否有歧义等。同时,预处理器还会验证用户权限。
  2. 查询优化
    • 优化器作用:优化器的目的是找到最好的执行计划。一条查询可以有多种执行方式,但最终都会返回相同的结果。优化器的作用就是选择其中成本最小的一种执行方式。
    • 生成执行计划:优化器会将MySQL语句转换为执行计划。这个执行计划表明了应该使用哪些索引执行查询、表之间的连接顺序等。MySQL使用基于成本的优化器(CBO),会预测一个查询使用某种执行计划的成本,并选择成本最小的一个。

四、查询执行

  1. 调用存储引擎:MySQL根据优化器生成的执行计划,调用存储引擎的API来执行查询。存储引擎是MySQL中负责存取真实数据的组件,它接收上层传下来的指令,对表中的数据进行读取或写入操作。
  2. 执行过程:查询执行引擎根据执行计划来完成整个查询。执行计划是一个数据结构(指令树),MySQL会根据执行计划给出的指令逐步执行。在执行过程中,有大量的操作需要调用存储引擎实现的接口来完成,这些接口即为“handler API”。

五、返回结果

  1. 结果返回:MySQL将查询结果集返回给客户端。这是一个增量逐步返回的过程,即当查询生成第一条结果时,MySQL就可以开始向客户端逐步返回结果了。这样可以节省服务端内存,并让客户端第一时间获得返回结果。
  2. 缓存查询结果(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子句、逻辑运算符(ANDOR)、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

ANDOR是逻辑运算符,用于在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

  1. 作用: WHERE 子句用于在数据被分组或聚合之前过滤行。
  2. 适用场景: 通常用于基于单行的条件来过滤数据。例如,选择特定列的值满足某个条件的行。
  3. 数据类型: 可以使用各种条件表达式,如比较运算符(=、<、>、<>、<=、>=)、逻辑运算符(AND、OR、NOT)等。
  4. 执行顺序: 在GROUP BY之前执行。
    示例:
SELECT * FROM employees
WHERE age > 30;

这个查询会选择所有年龄大于30的员工。
HAVING

  1. 作用: HAVING 子句用于在数据被分组和聚合之后过滤组。
  2. 适用场景: 通常用于基于聚合函数(如SUM、AVG、COUNT、MAX、MIN)的结果来过滤组。
  3. 数据类型: 通常与聚合函数一起使用,并且可以使用比较运算符和逻辑运算符。
  4. 执行顺序: 在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;

这条语句从locationstore_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;

这条语句首先使用内连接从locationstore_info两个表中检索数据,只返回那些Store_Name字段值在两个表中都存在的行。然后,它使用GROUP BY子句按location表中的Region字段对结果进行分组。最后,它使用SUM函数计算每个区域的总销售额,并将结果集中的列重命名为REGIONSALES

视图(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 列的结果集,并保留了所有重复的商店名称。

注意事项
  • 列数和数据类型:使用 UNIONUNION ALL 时,每个 SELECT 语句必须返回相同数量的列,并且这些列的数据类型必须兼容。
  • 排序:默认情况下,UNIONUNION ALL 操作符的结果集是按照列的顺序进行排序的,但这并不意味着结果集是按照某个特定的列排序的。如果需要排序,可以使用 ORDER BY 子句。
  • 性能UNION ALL 通常比 UNION 更快,因为 UNION 需要执行额外的步骤来去除重复行。
  • NULL 值:在 UNIONUNION 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连接locationstore_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