SQLite 的 UNION 子句 用于将多个 SELECT 查询的结果合并成一个结果集,自动去重。常用于:
- 合并多个表的数据
- 分表查询汇总
- 替代复杂
OR条件
基本语法
SELECT column1, column2, ... FROM table1
[WHERE ...]
UNION
SELECT column1, column2, ... FROM table2
[WHERE ...]
[ORDER BY ...]
[LIMIT ...];
- 每个
SELECT的列数必须相同 - 列的数据类型应兼容
- 默认去除重复行(全结果集去重)
UNION vs UNION ALL
| 操作符 | 去重 | 性能 | 使用场景 |
|---|---|---|---|
UNION | 是 | 较慢 | 需要唯一结果 |
UNION ALL | 否 | 更快 | 允许重复,推荐 |
示例表结构
-- 2024 年订单表
CREATE TABLE orders_2024 (
order_id INTEGER PRIMARY KEY,
user_id INTEGER,
product TEXT,
amount REAL,
order_date DATE
);
-- 2025 年订单表
CREATE TABLE orders_2025 (
order_id INTEGER PRIMARY KEY,
user_id INTEGER,
product TEXT,
amount REAL,
order_date DATE
);
-- 插入数据
INSERT INTO orders_2024 VALUES
(1, 101, 'Laptop', 1200, '2024-06-15'),
(2, 101, 'Mouse', 25, '2024-07-20'),
(3, 102, 'Keyboard', 80, '2024-08-10');
INSERT INTO orders_2025 VALUES
(1, 101, 'Monitor', 350, '2025-01-05'),
(2, 103, 'Webcam', 90, '2025-02-12'),
(3, 101, 'Laptop', 1200, '2025-03-20'); -- 与 2024 重复
1. 合并两个表(去重)
-- 查找所有年份的订单(去重)
SELECT user_id, product, amount FROM orders_2024
UNION
SELECT user_id, product, amount FROM orders_2025
ORDER BY amount DESC;
结果(Laptop 只出现一次):
user_id | product | amount
--------|----------|-------
101 | Laptop | 1200
101 | Monitor | 350
103 | Webcam | 90
102 | Keyboard | 80
101 | Mouse | 25
2. 使用 UNION ALL(保留重复)
SELECT user_id, product, amount FROM orders_2024
UNION ALL
SELECT user_id, product, amount FROM orders_2025
ORDER BY amount DESC;
结果(Laptop 出现两次):
101 | Laptop | 1200
101 | Laptop | 1200
101 | Monitor | 350
103 | Webcam | 90
102 | Keyboard | 80
101 | Mouse | 25
3. 不同列名对齐(使用别名)
SELECT user_id AS uid, product AS item, amount AS price FROM orders_2024
UNION ALL
SELECT customer_id AS uid, item_name AS item, total AS price FROM legacy_orders
4. 替代复杂 OR 条件
-- 查找 IT 或 HR 部门员工(避免 OR 影响索引)
SELECT name, department FROM employees WHERE department = 'IT'
UNION
SELECT name, department FROM employees WHERE department = 'HR';
比
WHERE department IN ('IT', 'HR')更易利用索引
5. 合并统计结果
-- 2024 年总销售额
SELECT '2024' AS year, SUM(amount) AS total FROM orders_2024
UNION ALL
SELECT '2025' AS year, SUM(amount) AS total FROM orders_2025
ORDER BY year;
6. 分页 + UNION
-- 第 2 页,每页 3 条
(SELECT * FROM orders_2024 ORDER BY order_date DESC LIMIT 3 OFFSET 3)
UNION ALL
(SELECT * FROM orders_2025 ORDER BY order_date DESC LIMIT 3 OFFSET 3)
ORDER BY order_date DESC
LIMIT 3;
注意:
ORDER BY和LIMIT需加括号作用于子查询
7. 性能优化
-- 为 UNION 字段建索引
CREATE INDEX idx_2024_user_amount ON orders_2024(user_id, amount);
CREATE INDEX idx_2025_user_amount ON orders_2025(user_id, amount);
UNION ALL比UNION快(无需排序去重)- 优先使用
UNION ALL除非明确需要去重
常见错误
| 错误 | 正确做法 |
|---|---|
| 列数不匹配 | 确保每个 SELECT 列数相同 |
| 类型不兼容 | TEXT vs INTEGER 会报错 |
ORDER BY 放错位置 | 必须在最后,或子查询内 |
-- 错误
SELECT id, name FROM users UNION SELECT email FROM profiles;
-- 正确
SELECT id, name FROM users UNION SELECT id, email FROM profiles;
快速参考
| 需求 | SQL |
|---|---|
| 合并去重 | UNION |
| 合并保留重复 | UNION ALL |
| 排序 | 最后加 ORDER BY |
| 分页 | 子查询加 LIMIT |
| 统计汇总 | 各表 SELECT 'label', SUM() |
最佳实践
- 优先用
UNION ALL(性能高) - 列数、顺序、类型必须一致
- 复杂排序/分页用子查询包裹
- 为连接字段建索引
需要我帮你写一个针对你分表的 UNION 查询吗?
请提供表名、公共字段和合并需求!