SQL语法之union和union all 的区别?

示例场景:

假设我们有两个表,记录了不同来源的员工信息:

  • employees_ny (纽约员工):

    idnamedepartment
    1AliceSales
    2BobIT
    3CarolHR
    4DavidSales(注意:David在NY表)
    5BobIT(注意:Bob在NY表重复出现,可能是录入错误)
  • employees_sf (旧金山员工):

    idnamedepartment
    101EmmaMarketing
    102FrankIT
    103AliceSales(注意:Alice在SF表)
    104DavidEngineering(注意:David在SF表,部门不同)
    105GraceHR

目标: 获取一个包含所有地点员工的合并列表。


示例 1: 使用 UNION ALL (保留所有行,包括重复)

SELECT id, name, department, 'NY' AS location FROM employees_ny
UNION ALL
SELECT id, name, department, 'SF' AS location FROM employees_sf;

结果 (UNION ALL):

idnamedepartmentlocation
1AliceSalesNY
2BobITNY
3CarolHRNY
4DavidSalesNY(David NY)
5BobITNY(Bob 重复行 - 保留)
101EmmaMarketingSF
102FrankITSF
103AliceSalesSF(Alice 重复行 - 保留,地点不同)
104DavidEngineeringSF(David SF - 保留,部门不同)
105GraceHRSF

解释:

  • 结果集是 employees_ny 和 employees_sf 所有行的直接堆叠。

  • 所有重复行都被保留:

    • Bob (id=2 和 id=5) 都在 NY,姓名和部门完全重复。

    • Alice (NY id=1 和 SF id=103) 姓名和部门重复,但来源地点不同(location 列区分)。

    • David (NY id=4 和 SF id=104) 姓名重复,但部门不同,地点也不同。

  • 效率较高: 数据库引擎只需要简单地将两个查询结果按顺序拼接起来,不需要进行额外的排序和去重操作。

  • 符合规则:两个 SELECT 都有 4 列 (idnamedepartmentlocation),对应列数据类型兼容。


示例 2: 使用 UNION (自动去重)

SELECT id, name, department, 'NY' AS location FROM employees_ny
UNION -- 这里省略了 ALL,等同于 UNION DISTINCT
SELECT id, name, department, 'SF' AS location FROM employees_sf;

结果 (UNION):

idnamedepartmentlocation
1AliceSalesNY
2BobITNY(只保留一个Bob)
3CarolHRNY
4DavidSalesNY(David NY)
5BobITNY(这个Bob被去重掉了!)
101EmmaMarketingSF
102FrankITSF
103AliceSalesSF(Alice SF 保留,因为location不同)
104DavidEngineeringSF(David SF 保留,因为department不同)
105GraceHRSF

解释:

  • 数据库引擎首先将两个表的所有行堆叠在一起(得到一个包含 10 行的临时结果集)。

  • 然后对这个整个临时结果集执行去重 (DISTINCT) 操作。

  • 去重规则: 只有当两行的 SELECT 列表中所有对应列的值都完全相同时,才会被认为是重复行并被移除一行。

    • Bob (NY id=2 和 id=5): id (2 vs 5) 不同,name (Bob vs Bob) 相同,department (IT vs IT) 相同,location (NY vs NY) 相同。关键点:id 列不同! 虽然名字、部门、地点一样,但 id 不同,所以不被视为重复行(注意:这个例子中 id 不同意味着它们是不同记录,UNION 不会仅根据 name 去重)

    • Alice (NY id=1 和 SF id=103): id (1 vs 103) 不同,name (Alice vs Alice) 相同,department (Sales vs Sales) 相同,location (NY vs SF) 不同。因为 location 值不同,所以这两行不是重复行,都被保留。

    • David (NY id=4 和 SF id=104): id (4 vs 104) 不同,name (David vs David) 相同,department (Sales vs Engineering) 不同location (NY vs SF) 不同。因为 department 和 location 都不同,所以这两行不是重复行,都被保留。

    • (如果存在两行所有列值都完全一样,UNION 会只保留其中一行)

  • 效率较低: 为了进行去重,数据库引擎通常需要对整个合并后的临时结果集进行排序SORT)操作,以便将相同的行分组在一起,然后移除重复项。这个排序操作在数据量大时是非常消耗资源的。因此 UNION 通常比 UNION ALL 慢得多

  • 符合规则:列数和数据类型要求同 UNION ALL


注意:

  1. all是可以省略,但是如果省略掉之后将结果拼接起来执行去重操作,如果有all则不会去重。没有设置all的时候执行合并,先对合并的数据进行排序操作,然后再执行去重操作,所以union的效率要远远低于union all。

  2. 合并的结果集必须要具有'相同的列数'。

  3. 合并的结果集中对应的列的'数据类型必须要相同'。

  4. 在实际工作过程中要用union all代替 union(一般实际工作中的数据都是优化过的数据,很少有重复的,但是也需要检查和以防万一)。去重请用其他的,distinct,group by 都可以。

补充注意点:

  • 列名: 最终结果集的列名通常取自第一个 SELECT 语句。即使第二个 SELECT 的列名不同(只要数据类型兼容),结果集也会使用第一个查询的列名。

  • 排序: 如果需要最终结果有序,必须在整个 UNION/UNION ALL 语句的最后加一个 ORDER BY 子句。在单个 SELECT 语句内加 ORDER BY 通常无效或会被覆盖(除非配合 LIMIT 等)。

### SQL UNIONUNION ALL区别 #### 1. 定义与功能 SQL 中的 `UNION` `UNION ALL` 都用于合并两个或多个 SELECT 查询的结果集。然而,它们在处理重复行时的行为不同。`UNION` 会自动去除结果集中的重复行[^2],而 `UNION ALL` 则保留所有行,包括重复的行[^4]。 #### 2. 性能差异 由于 `UNION` 需要额外的排序去重操作,其性能通常低于 `UNION ALL`[^1]。如果查询结果中不包含重复行,或者重复行的存在不影响业务逻辑,则应优先使用 `UNION ALL` 以提高查询效率。 #### 3. 语法示例 以下是 `UNION` `UNION ALL` 的语法及示例: ##### UNION 示例 ```sql SELECT column_name(s) FROM table_name1 WHERE column_name = value1 UNION SELECT column_name(s) FROM table_name2 WHERE column_name = value2; ``` ##### UNION ALL 示例 ```sql SELECT column_name(s) FROM table_name1 WHERE column_name = value1 UNION ALL SELECT column_name(s) FROM table_name2 WHERE column_name = value2; ``` 上述代码展示了如何使用 `UNION` `UNION ALL` 合并来自两个表的结果集[^4]。 #### 4. 使用场景 - 当需要确保结果集中没有重复行时,应使用 `UNION`[^2]。 - 当希望保留所有行且无需去重时,应使用 `UNION ALL`[^1]。 #### 5. 示例对比 以下是一个具体的对比示例,展示 `UNION` `UNION ALL` 的行为差异: 假设存在两个临时表 `#T1` `#T2`,分别插入如下数据: ```sql CREATE TABLE #T1 (data VARCHAR(10)); INSERT INTO #T1 SELECT 'abc' UNION ALL SELECT 'bcd' UNION ALL SELECT 'cde' UNION ALL SELECT 'def' UNION ALL SELECT 'efg'; CREATE TABLE #T2 (data VARCHAR(10)); INSERT INTO #T2 SELECT 'abc' UNION ALL SELECT 'cde' UNION ALL SELECT 'efg'; ``` 执行以下查询: ##### 使用 UNION ```sql SELECT data FROM #T1 UNION SELECT data FROM #T2; ``` 结果为: ``` abc bcd cde def efg ``` ##### 使用 UNION ALL ```sql SELECT data FROM #T1 UNION ALL SELECT data FROM #T2; ``` 结果为: ``` abc bcd cde def efg abc cde efg ``` 从结果可以看出,`UNION` 去除了重复的行,而 `UNION ALL` 保留了所有行[^2]。 ###
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值