0

0

SQL中的UNION操作是什么?合并查询结果的正确方法

星夢妙者

星夢妙者

发布时间:2025-09-06 17:11:02

|

913人浏览过

|

来源于php中文网

原创

UNION操作用于合并多个SELECT结果集,要求列数、顺序一致且数据类型兼容,UNION自动去重而UNION ALL保留重复行,优先使用UNION ALL以提升性能,列名由第一个SELECT决定,ORDER BY和LIMIT应置于最后,避免列不匹配和类型隐式转换问题,结合CAST、显式列名和括号提高可靠性与可读性。

sql中的union操作是什么?合并查询结果的正确方法

SQL中的UNION操作,简单来说,就是将两个或更多SELECT语句的结果集合并成一个单一的结果集。它主要用于当你需要从多个结构相似的表中,或者从同一个表的不同查询中,提取并整合数据时,提供了一种简洁而强大的方式。在我看来,它就像是数据世界的“拼接艺术家”,能把零散的信息汇聚成一个整体,方便我们统一分析和展示。

SQL中的UNION操作,其核心思想就是“行合并”。当你手头有两份或多份数据清单,它们的内容结构(列的数量和类型)大体一致,但数据来源不同,或者你只是想把它们“堆叠”起来看时,UNION就派上用场了。

它的基本语法非常直观:

SELECT column1, column2, ...
FROM table1
WHERE condition1
UNION [ALL]
SELECT column1, column2, ...
FROM table2
WHERE condition2;

这里有几个关键点,也是我个人在使用时最常思考和检查的地方:

  1. 列的数量和顺序必须一致:这是硬性要求。第一个SELECT语句选择了多少列,第二个(以及后续所有)SELECT语句就必须选择同样数量的列。而且,这些列的顺序也应该对应,这样数据合并后才不会“错位”。
  2. 数据类型兼容:虽然不要求数据类型完全相同,但它们必须是兼容的。比如,你不能把一个文本列和日期列直接UNION起来,这在逻辑上就说不通。数据库系统会尝试进行隐式转换,但最好还是确保类型接近或一致,避免潜在的错误或意外结果。
  3. 结果集的列名:最终结果集的列名通常由第一个SELECT语句的列名决定。这一点在使用别名时尤其需要注意,后续SELECT语句中的别名会被忽略。

举个例子,假设我们有一个

employees
表和一个
contractors
表,它们都有
id
,
name
,
email
这些列,现在我想看所有员工和承包商的联系方式:

SELECT id, name, email
FROM employees
WHERE status = 'active'
UNION
SELECT id, name, email
FROM contractors
WHERE end_date IS NULL;

这样,我就能得到一个包含所有活跃员工和当前承包商的统一列表了。UNION默认会移除重复的行,如果你想保留所有行,包括重复的,那就需要用到

UNION ALL

UNION 和 UNION ALL 有何不同?何时选择哪种操作?

UNION和UNION ALL之间的差异,说白了,就在于对“重复数据”的处理方式上。理解这一点,对于优化查询性能和确保数据准确性至关重要。

UNION (默认行为): 当你仅仅使用

UNION
关键字时,SQL数据库会在合并两个或多个结果集后,自动执行一个去重操作。这意味着,如果有多行在所有选定的列上都完全相同,那么最终的结果集中只会保留其中一行。

  • 特点:确保结果集的唯一性。
  • 适用场景:当你需要一个“不重复”的列表时,例如获取所有不重复的客户邮箱地址,或者所有参与过某个项目的不重复人员ID。
  • 性能考量:由于需要额外的去重步骤(通常涉及到排序或哈希操作),
    UNION
    的性能开销会比
    UNION ALL
    高。对于非常大的数据集,这个性能差异可能会很明显。

UNION ALL: 而

UNION ALL
则简单粗暴得多。它将所有SELECT语句的结果集直接堆叠起来,不会进行任何去重。这意味着,如果原始结果集中存在重复的行,它们会全部出现在最终的合并结果中。

  • 特点:保留所有行,包括重复的。
  • 适用场景:当你需要查看所有原始数据,或者你知道原始结果集中不会有重复行(或者重复行对你来说是有意义的,需要保留)时。例如,你可能想统计某个事件的总发生次数,即使是同一个人多次触发,也需要全部记录。
  • 性能考量:因为它不需要额外的去重步骤,
    UNION ALL
    通常比
    UNION
    执行得更快,尤其是在处理大量数据时。

何时选择哪种操作?

我的经验是,优先考虑

UNION ALL
。只有当你明确知道需要去重,并且去重是业务逻辑的一部分时,才使用
UNION

  • 如果对重复数据不敏感,或者你知道数据本身就没有重复,请用
    UNION ALL
    这样可以节省数据库的计算资源,提高查询速度。比如,你从两个不同的日志表中提取事件记录,即使事件内容完全一样,你也可能需要看到两次,因为它确实发生了两次。
  • 如果业务要求结果集中不能有任何重复,那么
    UNION
    是你的选择。
    比如,你要生成一个发送邮件的列表,肯定不希望同一个收件人收到多封邮件。

举个例子,假设我们有两个销售部门的销售记录表

sales_dept_a
sales_dept_b
,它们都有
order_id
,
customer_id
,
amount

如果你想知道所有销售订单的总金额,包括可能在两个部门都有记录的订单(虽然这种情况不常见,但作为例子),并且你希望保留所有记录:

SELECT order_id, customer_id, amount
FROM sales_dept_a
UNION ALL
SELECT order_id, customer_id, amount
FROM sales_dept_b;

但如果你想得到所有购买过的客户的唯一ID列表:

SELECT customer_id
FROM sales_dept_a
UNION
SELECT customer_id
FROM sales_dept_b;

这里

UNION
会确保每个
customer_id
只出现一次。

使用 UNION 操作时需要注意哪些常见陷阱和最佳实践?

在使用UNION操作时,虽然它功能强大,但如果不注意一些细节,很容易掉进坑里,或者写出效率低下的查询。以下是我在使用过程中总结的一些常见陷阱和最佳实践。

常见陷阱:

寻鲸AI
寻鲸AI

寻鲸AI是一款功能强大的人工智能写作工具,支持对话提问、内置多场景写作模板如写作辅助类、营销推广类等,更能一键写作各类策划方案。

下载
  1. 列不匹配导致的错误或意外结果

    • 列数量不一致:这是最常见的错误,直接导致SQL语法错误。数据库会明确告诉你SELECT列表中的项数不匹配。
    • 列类型不兼容:虽然有时数据库会尝试隐式转换,但这可能导致数据丢失(例如,将文本转换为数字失败)、数据截断或结果不符合预期。比如,你把一个
      VARCHAR
      类型的日期和
      DATE
      类型的日期UNION,结果可能都是字符串,但格式不统一。
    • 列顺序混乱:这不会导致语法错误,但会导致数据“错位”。比如,第一个SELECT是
      name, email
      ,第二个却是
      email, name
      ,结果就全乱了。
  2. ORDER BY
    子句的位置问题

    • ORDER BY
      子句只能应用于整个UNION结果集的最后。如果你在每个SELECT语句内部都添加
      ORDER BY
      ,除了第一个SELECT语句的
      ORDER BY
      可能会被某些数据库忽略外,其他都会报错。正确的做法是,将
      ORDER BY
      放在最后一个SELECT语句的后面,作用于所有合并后的数据。
  3. 性能问题

    • 滥用
      UNION
      :如果不需要去重,却使用了
      UNION
      而非
      UNION ALL
      ,会额外消耗资源进行去重操作,尤其是在数据量大时,性能会急剧下降。
    • 复杂的子查询:如果每个SELECT语句本身就包含复杂的JOIN或子查询,那么UNION操作会进一步增加整体查询的复杂度。

最佳实践:

  1. 明确列的定义

    • 显式列出所有列:不要使用
      SELECT *
      ,尤其是在UNION操作中。这不仅能避免未来表结构变化带来的问题,也能让你清楚地知道哪些列正在被合并。
    • 使用
      CAST
      CONVERT
      强制类型转换
      :如果列的数据类型确实不兼容,但逻辑上需要合并,可以使用
      CAST
      CONVERT
      函数将它们统一转换为兼容的类型。例如:
      SELECT CAST(numeric_id AS VARCHAR(20)) FROM table1 UNION ALL SELECT string_id FROM table2;
    • 保持列顺序一致:在编写查询时,养成习惯,让所有SELECT语句中的列顺序保持一致。
  2. 合理使用

    UNION ALL

    • 优先考虑
      UNION ALL
      :除非你明确需要去重,否则总是使用
      UNION ALL
      。这几乎是SQL性能优化的一个黄金法则。
    • 如果需要去重,但数据量巨大,考虑其他去重策略:例如,先用
      UNION ALL
      合并,然后在外层查询使用
      DISTINCT
      ,或者将结果插入临时表后再去重,有时可能会有更好的性能表现,但这需要具体分析。
  3. ORDER BY
    LIMIT
    的正确使用

    • ORDER BY
      放在最后
      :确保它作用于整个合并后的结果集。
    • LIMIT
      也放在最后
      :如果你只想获取合并结果集的前N行,
      LIMIT
      子句也应该放在整个UNION查询的末尾。
    (SELECT column1, column2 FROM tableA)
    UNION ALL
    (SELECT column1, column2 FROM tableB)
    ORDER BY column1 DESC
    LIMIT 10;

    注意:使用括号将每个SELECT语句包起来,虽然不是强制的,但在某些数据库中能提高可读性,并且在更复杂的场景下(比如与

    ORDER BY
    LIMIT
    结合时)能避免歧义。

  4. 使用别名提高可读性

    • 虽然最终结果集的列名由第一个SELECT决定,但在每个内部SELECT语句中使用别名可以提高代码的可读性,尤其是在处理复杂的表达式或函数时。

遵循这些实践,能让你更高效、更准确地利用UNION操作,避免不必要的麻烦。

除了 UNION,SQL 中还有哪些可以合并查询结果的方法?

除了UNION,SQL中还有其他几种强大的方式来合并或组合查询结果,它们各有侧重,解决的问题也不同。在我看来,理解这些不同工具的用途,是掌握SQL数据处理能力的关键。

  1. JOIN 操作(连接) 这是SQL中最常用的数据合并方式之一,但它与UNION的理念完全不同。JOIN操作不是将行“堆叠”起来,而是根据两个或多个表之间的关联条件,将它们的组合起来。

    • 核心思想:横向合并。它通过匹配共享的列(通常是主键和外键),将不同表中的相关信息放在同一行中。
    • 类型
      • INNER JOIN:只返回两个表中都存在匹配行的记录。
      • LEFT JOIN (LEFT OUTER JOIN):返回左表中的所有记录,以及右表中匹配的记录。如果右表中没有匹配,则右表的列显示为NULL。
      • RIGHT JOIN (RIGHT OUTER JOIN):与LEFT JOIN相反,返回右表中的所有记录,以及左表中匹配的记录。
      • FULL OUTER JOIN:返回当左表或右表中有匹配时所有的行。如果某行在另一个表中没有匹配,则对应列显示为NULL。
      • CROSS JOIN:返回两个表的笛卡尔积,即第一个表中的每一行与第二个表中的每一行组合。通常用于生成所有可能的组合。
    • 适用场景:当你需要从多个相关联的表中提取信息,并将它们展示在同一行时。例如,获取订单详情以及下订单的客户信息。
    SELECT o.order_id, o.order_date, c.customer_name, c.email
    FROM orders o
    INNER JOIN customers c ON o.customer_id = c.customer_id;
  2. 子查询(Subqueries)和公共表表达式(CTEs - Common Table Expressions) 子查询和CTEs本身不是直接合并结果集的操作,但它们是构建复杂查询、分步处理数据、最终达到“合并”效果的重要工具。它们允许你将一个查询的结果作为另一个查询的输入。

    • 核心思想:嵌套查询或分步查询。它们可以用来过滤数据、计算聚合值,或者作为另一个查询的数据源。
    • 子查询:可以将一个SELECT语句嵌套在另一个SELECT、INSERT、UPDATE或DELETE语句中。
      • 例如,
        SELECT * FROM products WHERE category_id IN (SELECT category_id FROM categories WHERE category_name = 'Electronics');
    • CTEs (WITH 子句):提供了一种更清晰、更可读的方式来组织复杂的查询。你可以定义一个或多个临时的、命名的结果集,然后在后续的查询中引用它们。
      • 适用场景:当你的查询逻辑非常复杂,需要多步处理时,CTEs能极大地提高代码的可读性和可维护性。它们也可以用于递归查询。
    WITH RecentOrders AS (
        SELECT order_id, customer_id, order_date
        FROM orders
        WHERE order_date >= DATE('now', '-7 days')
    ),
    HighValueCustomers AS (
        SELECT customer_id, customer_name
        FROM customers
        WHERE total_spent > 1000
    )
    SELECT ro.order_id, ro.order_date, hvc.customer_name
    FROM RecentOrders ro
    INNER JOIN HighValueCustomers hvc ON ro.customer_id = hvc.customer_id;

    这里,CTEs帮助我们清晰地定义了两个独立的逻辑块,然后通过JOIN将它们的结果合并。

  3. INSERT INTO ... SELECT FROM ... 这种方法不是为了在单个查询中“显示”合并结果,而是为了将一个或多个查询的结果永久地合并到一个目标表中。

    • 核心思想:数据迁移或数据整合。它将源查询的结果作为新行插入到目标表中。
    • 适用场景:当你需要将来自不同来源的数据整合到一个统一的报告表、历史表或数据仓库中时。这在ETL(抽取、转换、加载)过程中非常常见。
    -- 假设你有一个空的或需要更新的 consolidated_sales 表
    INSERT INTO consolidated_sales (sale_id, product_id, amount, sale_date)
    SELECT sale_id, product_id, amount, sale_date FROM daily_sales_region_a
    UNION ALL
    SELECT sale_id, product_id, amount, sale_date FROM daily_sales_region_b;

    这里,UNION ALL用来合并来自两个区域的日销售数据,然后一次性插入到总销售表中。

每种方法都有其独特的应用场景和优势。UNION适用于行合并,JOIN适用于列合并,而子查询/CTEs和

INSERT INTO ... SELECT
则提供了更灵活的数据处理和持久化能力。理解这些工具,并知道何时选择哪个,是成为一名高效SQL开发者的关键。

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
数据分析工具有哪些
数据分析工具有哪些

数据分析工具有Excel、SQL、Python、R、Tableau、Power BI、SAS、SPSS和MATLAB等。详细介绍:1、Excel,具有强大的计算和数据处理功能;2、SQL,可以进行数据查询、过滤、排序、聚合等操作;3、Python,拥有丰富的数据分析库;4、R,拥有丰富的统计分析库和图形库;5、Tableau,提供了直观易用的用户界面等等。

686

2023.10.12

SQL中distinct的用法
SQL中distinct的用法

SQL中distinct的语法是“SELECT DISTINCT column1, column2,...,FROM table_name;”。本专题为大家提供相关的文章、下载、课程内容,供大家免费下载体验。

327

2023.10.27

SQL中months_between使用方法
SQL中months_between使用方法

在SQL中,MONTHS_BETWEEN 是一个常见的函数,用于计算两个日期之间的月份差。想了解更多SQL的相关内容,可以阅读本专题下面的文章。

348

2024.02.23

SQL出现5120错误解决方法
SQL出现5120错误解决方法

SQL Server错误5120是由于没有足够的权限来访问或操作指定的数据库或文件引起的。想了解更多sql错误的相关内容,可以阅读本专题下面的文章。

1179

2024.03.06

sql procedure语法错误解决方法
sql procedure语法错误解决方法

sql procedure语法错误解决办法:1、仔细检查错误消息;2、检查语法规则;3、检查括号和引号;4、检查变量和参数;5、检查关键字和函数;6、逐步调试;7、参考文档和示例。想了解更多语法错误的相关内容,可以阅读本专题下面的文章。

359

2024.03.06

oracle数据库运行sql方法
oracle数据库运行sql方法

运行sql步骤包括:打开sql plus工具并连接到数据库。在提示符下输入sql语句。按enter键运行该语句。查看结果,错误消息或退出sql plus。想了解更多oracle数据库的相关内容,可以阅读本专题下面的文章。

778

2024.04.07

sql中where的含义
sql中where的含义

sql中where子句用于从表中过滤数据,它基于指定条件选择特定的行。想了解更多where的相关内容,可以阅读本专题下面的文章。

577

2024.04.29

sql中删除表的语句是什么
sql中删除表的语句是什么

sql中用于删除表的语句是drop table。语法为drop table table_name;该语句将永久删除指定表的表和数据。想了解更多sql的相关内容,可以阅读本专题下面的文章。

420

2024.04.29

拼多多赚钱的5种方法 拼多多赚钱的5种方法
拼多多赚钱的5种方法 拼多多赚钱的5种方法

在拼多多上赚钱主要可以通过无货源模式一件代发、精细化运营特色店铺、参与官方高流量活动、利用拼团机制社交裂变,以及成为多多进宝推广员这5种方法实现。核心策略在于通过低成本、高效率的供应链管理与营销,利用平台社交电商红利实现盈利。

1

2026.01.26

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
R 教程
R 教程

共45课时 | 5.5万人学习

SQL 教程
SQL 教程

共61课时 | 3.6万人学习

C 教程
C 教程

共75课时 | 4.2万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号