结果集合并(UNION / UNION ALL)

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)
对比项UNIONUNION ALL
去重
性能较慢(需排序去重)较快(直接拼接)
适用场景需要唯一结果确定无重复或允许重复

LINQ 中的对应写法

LINQ 中没有 UNION ALL 关键字,通过两个方法区分:

SQLLINQ说明
UNIONUnion()合并并去重
UNION ALLConcat()合并不去重

完整示例代码

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
UnionID: 1, 2, 3, 4(去重后 4 条)
ConcatID: 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)

发表回复

您的邮箱地址不会被公开。 必填项已用 * 标注