SQL 中的 UNION
在 SQL 中,UNION 用于合并两个查询结果集,要求列数相同、对应列类型兼容。
-- UNION:合并并去重
SELECT * FROM Student WHERE ID < 5
UNION
SELECT * FROM Student WHERE ID > 3
-- UNION ALL:合并不去重
SELECT * FROM Student WHERE ID < 5
UNION ALL
SELECT * FROM Student WHERE ID > 3Code language: HTML, XML (xml)
| 对比项 | UNION | UNION ALL |
|---|---|---|
| 去重 | 是 | 否 |
| 性能 | 较慢(需排序去重) | 较快(直接拼接) |
| 适用场景 | 需要唯一结果 | 确定无重复或允许重复 |
LINQ 中的对应写法
LINQ 中没有 UNION ALL 关键字,通过两个方法区分:
| SQL | LINQ | 说明 |
|---|---|---|
UNION | Union() | 合并并去重 |
UNION ALL | Concat() | 合并不去重 |
完整示例代码
using (var db = new DataClasses1DataContext())
{
// 两个子查询
var q1 = from s in db.Student
where s.ID < 3
select s;
var q2 = from s in db.Student
where s.ID < 5
select s;
// UNION —— 去重
var q = q1.Union(q2);
var r = q.ToList();
// UNION ALL —— 不去重(Concat)
var q3 = q1.Concat(q2);
var r3 = q3.ToList();
}Code language: JavaScript (javascript)
执行结果示意
假设 Student 表数据:
ID=1, ID=2, ID=3, ID=4
| 操作 | 结果 |
|---|---|
q1(ID < 3) | ID: 1, 2 |
q2(ID < 5) | ID: 1, 2, 3, 4 |
Union | ID: 1, 2, 3, 4(去重后 4 条) |
Concat | ID: 1, 2, 1, 2, 3, 4(不去重 6 条) |
不同实体合并为同一类型
Union / Concat 要求两边的元素类型一致。如果查询的是不同表,需投影为相同结构:
// 不同表合并为匿名类型(字段名、类型、顺序须一致)
var q = (from c in db.Customers
select new { Name = c.ContactName, City = c.City })
.Union(
from e in db.Employees
select new { Name = e.Name, City = e.City }
);Code language: JavaScript (javascript)
生成的 SQL
Union(去重):
SELECT [t2].[ID], [t2].[Name], [t2].[ClassID], ...
FROM (
SELECT [t0].[ID], [t0].[Name], [t0].[ClassID], ...
FROM [Student] AS [t0]
WHERE [t0].[ID] < 3
UNION
SELECT [t1].[ID], [t1].[Name], [t1].[ClassID], ...
FROM [Student] AS [t1]
WHERE [t1].[ID] < 5
) AS [t2]Code language: CSS (css)
Concat(不去重):
SELECT [t2].[ID], [t2].[Name], [t2].[ClassID], ...
FROM (
SELECT [t0].[ID], [t0].[Name], [t0].[ClassID], ...
FROM [Student] AS [t0]
WHERE [t0].[ID] < 3
UNION ALL
SELECT [t1].[ID], [t1].[Name], [t1].[ClassID], ...
FROM [Student] AS [t1]
WHERE [t1].[ID] < 5
) AS [t2]Code language: CSS (css)
Previous: EXISTS 语义在 LINQ 中的实现(Any)
Next: 结果集交集(Intersect)