ORMX Union 查询功能 - 开发日志,Union 查询,UNION, UNION ALL, 联合查询,多表查询,集合操作 - 学习 ORMX 的 Union 查询功能,包括 UNION、UNION ALL 操作、多表联合查询、排序分页和聚合函数等高级用法。

您当前正在浏览的是本站SEO版网页

请点击确认

马上提升浏览体验

ORMX Union 查询功能

编程 数据库 阅读:0
4/10/2026 9:42:24 AM

学习 ORMX 的 Union 查询功能,包括 UNION、UNION ALL 操作、多表联合查询、排序分页和聚合函数等高级用法。 关键字:Union 查询,UNION, UNION ALL, 联合查询,多表查询,集合操作

Union 查询

Union 概述

Union(联合查询)是 SQL 中用于合并多个 SELECT 查询结果集的 powerful 功能。ORMX 提供了完整的 Union 支持,让您能够轻松地将多个查询的结果组合在一起。

UNION 与 UNION ALL 的区别

  • UNION:合并多个查询结果,并自动去除重复行
  • UNION ALL:合并多个查询结果,保留所有行(包括重复行),性能更好

使用场景

Union 查询适用于以下场景:

  • 合并来自同一表的不同条件的查询结果
  • 合并来自多个结构相似的表的数据
  • 将多个独立查询的结果组合成一个结果集
  • 实现复杂的数据筛选和分类
// 示例:查询年龄大于 30 的用户和姓名为"Alice"的用户
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Alice"))
    .GetList();

基本 Union 操作

创建 Union 查询

使用 UnionTable 方法创建第一个查询(作为主 SELECT),然后使用 UnionUnionAll 添加更多查询:

// 查询年龄大于 30 的用户
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Alice"))
    .GetList();

Console.WriteLine(<div class="latex">$"结果数量:{result.Count}");
foreach (var user in result)
{
    Console.WriteLine($</div>"用户:{user.Username}, 年龄:{user.Age}");
}

生成的 SQL:

SELECT * FROM "Users" WHERE "Age" > @p0 
UNION ALL 
SELECT * FROM "Users" WHERE "Username" = @p1

UNION(去重)

使用 Union 方法执行去重的联合查询:

// 查询年龄>=25 的用户,并去重
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age >= 25))
    .Union<User>(qb => qb.Where(u => u.Username == "Alice"))
    .GetList();

// 即使 Alice 的年龄>=25,也只会返回一次
Console.WriteLine(<div class="latex">$"去重后的用户数量:{result.Count}");

生成的 SQL:

SELECT * FROM "Users" WHERE "Age" >= @p0 
UNION 
SELECT * FROM "Users" WHERE "Username" = @p1

多个 Union 操作

可以链式调用多个 Union 操作:

// 合并三个查询的结果
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age < 30))
    .UnionAll<User>(qb => qb.Where(u => u.Age > 40))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Admin"))
    .GetList();

Console.WriteLine($</div>"合并结果:{result.Count} 个用户");

生成的 SQL:

SELECT * FROM "Users" WHERE "Age" < @p0 
UNION ALL 
SELECT * FROM "Users" WHERE "Age" > @p1
UNION ALL 
SELECT * FROM "Users" WHERE "Username" = @p2

Union 上下文查询

使用 Union 上下文

Union 查询可能涉及多张表,使用上下文方式可以统一访问所有参与 Union 的表:

// 使用上下文方式访问 Union 中的表
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Alice"))
    // 使用上下文方式访问 Union 中的表
    .Where(ctx => ctx.As<User>().Age > 25)
    .GetList();

生成的 SQL:

SELECT * FROM (
    SELECT * FROM "Users" WHERE "Age" > @p1 
    UNION ALL 
    SELECT * FROM "Users" WHERE "Username" = @p2
) AS union_result 
WHERE "Age" > @p0

上下文的优势

使用上下文方式的优势:

  • 统一访问:通过 ctx.As<T>() 统一访问所有参与 Union 的表
  • 外层过滤:可以对 Union 后的结果集进行再次过滤
  • 灵活性:适用于复杂的 Union 查询场景
// 先 Union,然后在外层过滤
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Alice"))
    .Where(ctx => ctx.As<User>().Age > 25)  // 对外层结果过滤
    .GetList();

Union 排序和分页

OrderBy 排序

使用 OrderBy 对 Union 结果进行排序:

// 按年龄升序排序
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age == 25))
    .UnionAll<User>(qb => qb.Where(u => u.Age == 35))
    .OrderBy(ctx => ctx.As<User>().Age)
    .GetList();

// 结果按年龄从小到大排列
foreach (var user in result)
{
    Console.WriteLine(<div class="latex">$"用户:{user.Username}, 年龄:{user.Age}");
}

生成的 SQL:

SELECT * FROM (
    SELECT * FROM "Users" WHERE "Age" = @p0 
    UNION ALL 
    SELECT * FROM "Users" WHERE "Age" = @p1
) AS union_result 
ORDER BY "Age" ASC

OrderByDesc 降序

使用 OrderByDesc 对 Union 结果进行降序排序:

// 按年龄降序排序
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age == 30))
    .UnionAll<User>(qb => qb.Where(u => u.Age == 35))
    .OrderByDesc(ctx => ctx.As<User>().Age)
    .GetList();

// 结果按年龄从大到小排列

生成的 SQL:

SELECT * FROM (
    SELECT * FROM "Users" WHERE "Age" = @p0 
    UNION ALL 
    SELECT * FROM "Users" WHERE "Age" = @p1
) AS union_result 
ORDER BY "Age" DESC

Limit 分页

使用 Limit 对 Union 结果进行分页:

// 只返回第一条记录
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age == 25))
    .UnionAll<User>(qb => qb.Where(u => u.Age == 30))
    .Limit(1)
    .GetList();

Console.WriteLine($</div>"第一条记录:{result[0].Username}");

生成的 SQL:

SELECT * FROM (
    SELECT * FROM "Users" WHERE "Age" = @p0 
    UNION ALL 
    SELECT * FROM "Users" WHERE "Age" = @p1
) AS union_result 
LIMIT 1

组合使用

可以组合使用排序和分页:

// 按年龄排序,然后取前 5 条
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 20))
    .UnionAll<User>(qb => qb.Where(u => u.Username.Contains("a")))
    .OrderBy(ctx => ctx.As<User>().Age)
    .Limit(5)
    .GetList();

Union 聚合函数

Count 计数

使用 Count 统计 Union 结果的行数:

// 统计 Union 结果的总行数
var totalCount = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Alice"))
    .Count();

Console.WriteLine(<div class="latex">$"总行数:{totalCount}");

Max/Min 最值

使用 MaxMin 获取 Union 结果的最大值和最小值:

// 获取 Union 结果中的最大年龄
var maxAge = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 20))
    .UnionAll<User>(qb => qb.Where(u => u.Username.Contains("a")))
    .Max(u => u.Age);

Console.WriteLine($</div>"最大年龄:{maxAge}");

// 获取 Union 结果中的最小年龄
var minAge = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 20))
    .UnionAll<User>(qb => qb.Where(u => u.Username.Contains("a")))
    .Min(u => u.Age);

Console.WriteLine(<div class="latex">$"最小年龄:{minAge}");

Sum/Avg 求和与平均

使用 SumAvg 计算 Union 结果的总和与平均值:

// 计算 Union 结果的年龄总和
var sumAge = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 20))
    .UnionAll<User>(qb => qb.Where(u => u.Username.Contains("a")))
    .Sum(u => u.Age);

Console.WriteLine($</div>"年龄总和:{sumAge}");

// 计算 Union 结果的平均年龄
var avgAge = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 20))
    .UnionAll<User>(qb => qb.Where(u => u.Username.Contains("a")))
    .Avg(u => u.Age);

Console.WriteLine(<div class="latex">$"平均年龄:{avgAge}");

多表 Union 查询

不同表的 Union

Union 不仅可以用于同一张表,还可以用于结构相似的不同表:

// 假设有 User 和 Admin 两张结构相似的表
public class User
{
    public int Id { get; set; }
    public string Username { get; set; }
    public int Age { get; set; }
}

public class Admin
{
    public int Id { get; set; }
    public string Username { get; set; }
    public int Age { get; set; }
}

// 合并用户和管理员
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<Admin>(qb => qb.Where(a => a.Age > 50))
    .GetList();

foreach (var item in result)
{
    Console.WriteLine($</div>"名称:{item.Username}, 年龄:{item.Age}");
}

注意: 参与 Union 的不同表必须有相似的列结构(列名和数据类型兼容)。

使用 DTO 接收结果

当 Union 涉及多张表时,建议使用 DTO 来接收结果:

public class PersonDto
{
    public int Id { get; set; }
    public string Name { get; set; }
    public int Age { get; set; }
}

// 使用 DTO 接收 Union 结果
var result = tableManager.UnionTable<User>(qb => qb.Select(u => new { u.Id, u.Username, u.Age }))
    .UnionAll<Admin>(qb => qb.Select(a => new { a.Id, a.Username, a.Age }))
    .GetList();

复杂条件查询

复杂 Where 条件

在 Union 子查询中使用复杂的 Where 条件:

// 每个 Union 子句都可以有独立的复杂条件
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 20 && u.Age < 35))
    .UnionAll<User>(qb => qb.Where(u => u.Username.Contains("a") || u.Username.Contains("e")))
    .GetList();

生成的 SQL:

SELECT * FROM "Users" WHERE ("Age" > @p0) AND ("Age" < @p1) 
UNION ALL 
SELECT * FROM "Users" WHERE ("Username" LIKE @p2) OR ("Username" LIKE @p3)

外层 Where 过滤

结合上下文使用外层 Where 过滤:

// 内层 Union,外层过滤
var result = tableManager.UnionTable<User>(qb => qb.Where(u => u.Age > 30))
    .UnionAll<User>(qb => qb.Where(u => u.Username == "Alice"))
    .Where(ctx => ctx.As<User>().Age > 25)  // 外层过滤
    .OrderBy(ctx => ctx.As<User>().Age)
    .GetList();

最佳实践

性能优化

  • 优先使用 UNION ALL:如果不需要去重,使用 UNION ALL 性能更好
  • 减少 Union 子句数量:过多的 Union 子句会影响查询性能
  • 合理使用索引:确保 Union 子句中的 Where 条件能使用索引

代码组织

  • 使用有意义的变量名:让代码更易读
  • 添加注释:说明每个 Union 子句的目的
  • 使用 DTO:当 Union 涉及多表时,使用 DTO 接收结果
// 良好的代码组织示例
// 查询活跃用户和 VIP 用户
var activeOrVipUsers = tableManager.UnionTable<User>(
    qb => qb.Where(u => u.IsActive == true)  // 活跃用户
)
.UnionAll<User>(
    qb => qb.Where(u => u.IsVip == true)  // VIP 用户
)
.OrderBy(ctx => ctx.As<User>().Username)
.GetList();

注意事项

  • 列数必须相同:参与 Union 的所有查询必须有相同数量的列
  • 列类型必须兼容:对应位置的列数据类型必须兼容
  • 列名以第一个查询为准:结果集的列名由第一个 SELECT 决定
  • ORDER BY 位置:ORDER BY 只能放在最后一个 Union 子句之后

完整示例

用户分类查询

// 查询新用户、活跃用户和 VIP 用户
var result = tableManager.UnionTable<User>(
    qb => qb.Where(u => u.CreatedAt > DateTime.Now.AddDays(-7))  // 新用户
)
.UnionAll<User>(
    qb => qb.Where(u => u.LastLoginAt > DateTime.Now.AddDays(-1))  // 活跃用户
)
.UnionAll<User>(
    qb => qb.Where(u => u.IsVip == true)  // VIP 用户
)
.OrderBy(ctx => ctx.As<User>().Id)
.Limit(10)
.GetList();

Console.WriteLine(<div class="latex">$"查询结果:{result.Count} 个用户");
foreach (var user in result)
{
    Console.WriteLine($</div>"用户:{user.Username}");
}

多地区数据合并

// 假设有不同地区的用户表
var allUsers = tableManager.UnionTable<User>(
    qb => qb.Where(u => u.Region == "Beijing")
)
.UnionAll<User>(
    qb => qb.Where(u => u.Region == "Shanghai")
)
.UnionAll<User>(
    qb => qb.Where(u => u.Region == "Guangzhou")
)
.Count();

Console.WriteLine($"三个地区的总用户数:{allUsers}");

小结

本章介绍了 ORMX 的 Union 查询功能,包括:

  • 基本操作:使用 UnionTableUnionUnionAll 创建联合查询
  • 上下文查询:使用 ctx.As<T>() 统一访问 Union 中的表
  • 排序分页:使用 OrderByOrderByDescLimit 控制结果
  • 聚合函数:使用 CountMaxMinSumAvg 统计结果
  • 多表 Union:合并结构相似的不同表的数据
  • 最佳实践:性能优化和代码组织建议

Union 是处理多查询合并的强大工具,合理使用可以简化复杂查询场景。