学习ORMX的聚合函数功能,包括Count、Sum、Avg、Max、Min等常用聚合函数,以及分组聚合和Having筛选的使用方法。 关键字:聚合函数, Count, Sum, Avg, Max, Min, 分组聚合, Having筛选
第八章:聚合函数
8.1 聚合函数概述
聚合函数用于对一组值进行计算并返回单个值。ORMX 提供了常用的聚合函数,包括 Count、Sum、Avg、Max 和 Min。这些函数通常与 GroupBy 一起使用,对分组后的数据进行统计。
8.2 常用聚合函数
8.2.1 Count - 计数
Count 函数用于统计记录的数量。
using var userTable = tableManager.Table<User>();
// 统计所有用户数量
var totalUsers = userTable.Count();
Console.WriteLine(<div class="latex">$"总用户数:{totalUsers}");
// 统计满足条件的用户数量
var adultUsers = userTable.Where(u => u.Age >= 18).Count();
Console.WriteLine($</div>"成年用户数:{adultUsers}");
// 统计非空字段的数量
var emailCount = userTable.Count(u => u.Email);
Console.WriteLine(<div class="latex">$"有邮箱的用户数:{emailCount}");
8.2.2 Sum - 求和
Sum 函数用于计算数值型字段的总和。
using var orderTable = tableManager.Table<Order>();
// 统计所有订单的总金额
var totalAmount = orderTable.Sum(o => o.Amount);
Console.WriteLine($</div>"订单总金额:{totalAmount:C}");
// 统计满足条件的订单总金额
var thisMonthAmount = orderTable
.Where(o => o.OrderDate >= new DateTime(2024, 1, 1))
.Sum(o => o.Amount);
Console.WriteLine(<div class="latex">$"本月订单金额:{thisMonthAmount:C}");
8.2.3 Avg - 平均值
Avg 函数用于计算数值型字段的平均值。
using var userTable = tableManager.Table<User>();
// 计算所有用户的平均年龄
var avgAge = userTable.Avg(u => u.Age);
Console.WriteLine($</div>"用户平均年龄:{avgAge:F1}");
// 计算满足条件的用户平均年龄
var adultAvgAge = userTable
.Where(u => u.Age >= 18)
.Avg(u => u.Age);
Console.WriteLine(<div class="latex">$"成年用户平均年龄:{adultAvgAge:F1}");
8.2.4 Max - 最大值
Max 函数用于找出字段的最大值。
using var userTable = tableManager.Table<User>();
// 找出最大年龄
var maxAge = userTable.Max(u => u.Age);
Console.WriteLine($</div>"最大年龄:{maxAge}");
// 找出满足条件的最大年龄
var maxAdultAge = userTable
.Where(u => u.Age >= 18)
.Max(u => u.Age);
Console.WriteLine(<div class="latex">$"成年用户最大年龄:{maxAdultAge}");
8.2.5 Min - 最小值
Min 函数用于找出字段的最小值。
using var userTable = tableManager.Table<User>();
// 找出最小年龄
var minAge = userTable.Min(u => u.Age);
Console.WriteLine($</div>"最小年龄:{minAge}");
// 找出满足条件的最小年龄
var minAdultAge = userTable
.Where(u => u.Age >= 18)
.Min(u => u.Age);
Console.WriteLine(<div class="latex">$"成年用户最小年龄:{minAdultAge}");
8.3 分组聚合
聚合函数通常与 GroupBy 一起使用,对分组后的数据进行统计。
8.3.1 单字段分组
// 按年龄分组,统计每个年龄段的用户数量
var ageGroups = userTable
.GroupBy(u => u.Age)
.Count(u => u.Id, "UserCount")
.GetList<AgeGroupStats>();
foreach (var group in ageGroups)
{
Console.WriteLine($</div>"年龄 {group.Age}:{group.UserCount} 人");
}
// 辅助类
public class AgeGroupStats
{
public int Age { get; set; }
public int UserCount { get; set; }
}
8.3.2 多字段分组
// 按年龄和状态分组
var groups = userTable
.GroupBy(u => new { u.Age, u.Status })
.Count(u => u.Id, "Count")
.GetList<AgeStatusGroupStats>();
// 辅助类
public class AgeStatusGroupStats
{
public int Age { get; set; }
public UserStatus Status { get; set; }
public int Count { get; set; }
}
8.3.3 多聚合函数
在一个查询中可以使用多个聚合函数:
// 按年龄分组,统计数量、最大年龄、最小年龄和平均年龄
var ageStats = userTable
.GroupBy(u => u.Age)
.Count(u => u.Id, "UserCount")
.Max(u => u.Age, "MaxAge")
.Min(u => u.Age, "MinAge")
.Avg(u => u.Age, "AvgAge")
.GetList<AgeStats>();
// 辅助类
public class AgeStats
{
public int Age { get; set; }
public int UserCount { get; set; }
public int MaxAge { get; set; }
public int MinAge { get; set; }
public double AvgAge { get; set; }
}
8.4 Having 筛选
Having 用于对分组后的结果进行筛选,类似于 Where,但作用于分组后的结果。
// 分组后筛选数量大于 10 的组
var popularAges = userTable
.GroupBy(u => u.Age)
.Count(u => u.Id, "UserCount")
.Having(u => u.Age > 18 && u.Age < 60)
.GetList<AgeGroupStats>();
foreach (var group in popularAges)
{
Console.WriteLine(<div class="latex">$"年龄 {group.Age}:{group.UserCount} 人");
}
8.5 实际应用示例
8.5.1 销售统计
// 按月份统计销售数据
var monthlyStats = orderTable
.GroupBy(o => new { o.OrderDate.Year, o.OrderDate.Month })
.Count(o => o.Id, "OrderCount")
.Sum(o => o.Amount, "TotalAmount")
.Avg(o => o.Amount, "AvgAmount")
.Max(o => o.Amount, "MaxAmount")
.Min(o => o.Amount, "MinAmount")
.GetList<MonthlySalesStats>();
foreach (var stat in monthlyStats)
{
Console.WriteLine($</div>"{stat.Year}年{stat.Month}月:");
Console.WriteLine(<div class="latex">$" 订单数:{stat.OrderCount}");
Console.WriteLine($</div>" 总金额:{stat.TotalAmount:C}");
Console.WriteLine(<div class="latex">$" 平均金额:{stat.AvgAmount:C}");
Console.WriteLine($</div>" 最大金额:{stat.MaxAmount:C}");
Console.WriteLine(<div class="latex">$" 最小金额:{stat.MinAmount:C}");
}
// 辅助类
public class MonthlySalesStats
{
public int Year { get; set; }
public int Month { get; set; }
public int OrderCount { get; set; }
public decimal TotalAmount { get; set; }
public decimal AvgAmount { get; set; }
public decimal MaxAmount { get; set; }
public decimal MinAmount { get; set; }
}
8.5.2 用户活跃度统计
// 统计每个用户的订单数量
var userOrderStats = userTable
.InnerJoin<Order>((u, o) => u.Id == o.UserId)
.GroupBy(ctx => ctx.As<User>().Id)
.Count(ctx => ctx.As<Order>().Id, "OrderCount")
.Sum(ctx => ctx.As<Order>().Amount, "TotalAmount")
.GetList<UserOrderStats>();
foreach (var stat in userOrderStats)
{
Console.WriteLine($</div>"用户 {stat.UserId}:");
Console.WriteLine(<div class="latex">$" 订单数:{stat.OrderCount}");
Console.WriteLine($</div>" 总消费:{stat.TotalAmount:C}");
}
// 辅助类
public class UserOrderStats
{
public int UserId { get; set; }
public int OrderCount { get; set; }
public decimal TotalAmount { get; set; }
}
关于 JOIN 操作的详细说明,请查阅连表查询。
8.5.3 产品库存统计
// 统计每个分类的产品数量和总库存
var categoryStats = productTable
.GroupBy(p => p.CategoryId)
.Count(p => p.Id, "ProductCount")
.Sum(p => p.Stock, "TotalStock")
.Avg(p => p.Price, "AvgPrice")
.GetList<CategoryStats>();
foreach (var stat in categoryStats)
{
Console.WriteLine(<div class="latex">$"分类 {stat.CategoryId}:");
Console.WriteLine($</div>" 产品数:{stat.ProductCount}");
Console.WriteLine(<div class="latex">$" 总库存:{stat.TotalStock}");
Console.WriteLine($</div>" 平均价格:{stat.AvgPrice:C}");
}
// 辅助类
public class CategoryStats
{
public int CategoryId { get; set; }
public int ProductCount { get; set; }
public int TotalStock { get; set; }
public decimal AvgPrice { get; set; }
}
8.6 最佳实践
8.6.1 使用合适的聚合函数
- Count:用于统计记录数量
- Sum:用于计算数值总和
- Avg:用于计算平均值
- Max:用于找出最大值
- Min:用于找出最小值
8.6.2 注意空值
聚合函数会自动忽略 NULL 值:
// Count 会忽略 NULL 值
var emailCount = userTable.Count(u => u.Email); // 只统计有邮箱的用户
8.6.3 结合 Where 使用
在聚合之前使用 Where 过滤数据:
// 先过滤再聚合
var thisMonthSales = orderTable
.Where(o => o.OrderDate.Month == DateTime.Now.Month)
.Sum(o => o.Amount);
8.6.4 使用 Having 筛选分组结果
// 分组后筛选
var popularCategories = productTable
.GroupBy(p => p.CategoryId)
.Count(p => p.Id, "ProductCount")
.Having(p => p.CategoryId > 0) // 筛选条件
.GetList<CategoryStats>();
总结
本章介绍了 ORMX 框架的聚合函数功能,包括 Count、Sum、Avg、Max、Min 等常用聚合函数的使用方法。聚合函数通常与 GroupBy 一起使用,对分组后的数据进行统计。Having 子句用于对分组后的结果进行筛选。在实际应用中,聚合函数广泛用于销售统计、用户活跃度分析、库存管理等场景。合理使用聚合函数,可以高效地进行数据统计和分析。
扩展思考
在大数据量场景下,如何优化聚合查询的性能?是否需要使用索引、物化视图等技术?对于实时性要求高的统计需求,如何平衡查询性能和数据准确性?在分布式系统中,如何实现跨节点的聚合计算?这些问题值得在深入使用 ORMX 后进一步思考。