编辑
2025-09-22
C#
00

目录

实体类
Product 实体类
Sale 实体类
基本分组查询
按单个字段分组
按多个字段分组
分组后的进一步操作
分组后筛选
分组后排序
连接查询后分组

SqlSugar是一个轻量级但功能强大的.NET ORM框架,它提供了丰富的查询功能,包括灵活的分组查询操作。分组查询是数据库操作中常见的需求之一,用于将数据集合按照某个或某些字段进行分组,并对每个组进行聚合运算。在本文中,我们将通过几个例子探讨如何使用SqlSugar进行分组查询。

实体类

Product 实体类

Product类代表商品信息,假设每个商品都有一个唯一的ID、名称、类别ID和价格。

C#
[SugarTable("Product")] public class Product { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public string Name { get; set; } public int CategoryId { get; set; } public decimal Price { get; set; } }

在这个类中,SugarTableSugarColumn是SqlSugar提供的特性,用于映射实体类到数据库的表和列。IsPrimaryKey标记该字段为主键,IsIdentity表示该字段是自增的。

Sale 实体类

Sale类代表销售记录,包括每次销售的唯一ID、销售的商品ID、销售数量、销售金额和销售年份。

C#
[SugarTable("Sale")] public class Sale { [SugarColumn(IsPrimaryKey = true, IsIdentity = true)] public int Id { get; set; } public int ProductId { get; set; } public int Quantity { get; set; } public decimal Amount { get; set; } public int SaleYear { get; set; } }

Sale实体类中,我们同样使用SugarTableSugarColumn特性来定义与数据库表和列的映射。ProductId字段表示这次销售中所售出商品的ID,它可以与Product表中的Id字段关联。

基本分组查询

按单个字段分组

假设我们有一个Product表,我们需要按照CategoryId字段对商品进行分组,并计算每个类别下的商品数量。

C#
// 创建一个针对Product实体的SqlSugar仓库实例 var productRepository = new SqlSugarRepository<Product>(); // 使用仓库实例的AsQueryable方法开始构建查询 var categoryCount = productRepository.AsQueryable() // 根据CategoryId字段对Product表中的记录进行分组 .GroupBy(p => p.CategoryId) // 选择每个分组的CategoryId和该CategoryId下的记录数 // SqlFunc.AggregateCount用于计算每个分组中CategoryId的数量 .Select(g => new { CategoryId = g.CategoryId, Count = SqlFunc.AggregateCount(g.CategoryId) }) // 将查询结果转换为列表 .ToList(); // 遍历查询结果列表 foreach (var item in categoryCount) { // 打印每个类别的ID和该类别下的商品数量 Console.WriteLine($"{item.CategoryId}\t{item.Count}"); }

image.png

按多个字段分组

如果要根据多个字段进行分组,例如根据CategoryIdSaleYear分组,并计算每组的销售总额,可以这样做:

C#
// 定义一个异步的主入口函数 static async Task Main() { // 创建一个针对Sale实体的SqlSugar仓库实例 var saleRepository = new SqlSugarRepository<Sale>(); // 使用仓库实例的AsQueryable方法开始构建查询 var saleSummary = saleRepository.AsQueryable() // 根据ProductId和SaleYear字段对Sale表中的记录进行分组 .GroupBy(s => new { s.ProductId, s.SaleYear }) // 选择每个分组的ProductId, SaleYear和该分组下所有记录的Amount字段之和 // SqlFunc.AggregateSum用于计算每个分组中Amount的总和 .Select(g => new { g.ProductId, g.SaleYear, TotalSale = SqlFunc.AggregateSum(g.Amount) }) // 将查询结果转换为列表 .ToList(); // 遍历查询结果列表 foreach (var item in saleSummary) { // 打印每个产品每年的销售总额 Console.WriteLine($"{item.ProductId}\t{item.SaleYear}\t{item.TotalSale}"); } }

image.png

分组后的进一步操作

分组后筛选

分组聚合后,我们可能需要对结果进行筛选,比如找出销售总额超过一定值的分组。

C#
// 定义一个异步的主入口函数 static async Task Main() { // 创建一个针对Sale实体的SqlSugar仓库实例 var saleRepository = new SqlSugarRepository<Sale>(); // 使用仓库实例的AsQueryable方法开始构建查询 var saleSummary = saleRepository.AsQueryable() // 根据ProductId和SaleYear字段对Sale表中的记录进行分组 .GroupBy(s => new { s.ProductId, s.SaleYear }) // 选择每个分组的ProductId, SaleYear和该分组下所有记录的Amount字段之和 // SqlFunc.AggregateSum用于计算每个分组中Amount的总和,即总销售额 .Select(g => new { g.ProductId, g.SaleYear, TotalSale = SqlFunc.AggregateSum(g.Amount) }) // 将之前的查询结果作为一个新的表进行处理 .MergeTable() // 从新表中筛选出总销售额超过10000的记录 .Where(x => x.TotalSale > 10000) // 将查询结果转换为列表 .ToList(); // 遍历查询结果列表 foreach (var item in saleSummary) { // 打印每个满足条件的产品的ID、销售年份和总销售额 Console.WriteLine($"{item.ProductId}\t{item.SaleYear}\t{item.TotalSale}"); } }
  1. 构建查询:首先,通过AsQueryable方法开始构建对Sale表的查询。
  2. 分组:使用GroupBy方法按ProductIdSaleYear对记录进行分组。
  3. 选择:通过Select方法选择每个分组的ProductIdSaleYearTotalSale(总销售额),其中使用SqlFunc.AggregateSum来计算每个分组的销售总额。
  4. 合并表格MergeTable方法将之前的查询结果视为一个新的表,以便进行进一步的处理。
  5. 筛选:使用Where方法从新表中筛选出总销售额超过10000的记录。
  6. 结果转换:使用ToList方法将查询结果转换为列表。
  7. 遍历和打印:最后,遍历查询结果列表,打印每个满足条件的产品的ID、销售年份和总销售额。

分组后排序

对分组聚合的结果进行排序,例如按销售总额降序排列。

C#
var saleRepository = new SqlSugarRepository<Sale>(); var saleSummary = saleRepository.AsQueryable() .GroupBy(s => new { s.ProductId, s.SaleYear }) .Select(g => new { g.ProductId, g.SaleYear, TotalSale = SqlFunc.AggregateSum(g.Amount) }) .MergeTable() .OrderByDescending(g=>g.TotalSale) .ToList();

连接查询后分组

在进行连接查询后,我们也可以对结果进行分组。比如连接Product表和Sale表后,按商品类别分组计算销唀总额。

C#
// 定义一个异步的主入口函数 static async Task Main() { // 创建一个针对Sale实体的SqlSugar仓库实例 var saleRepository = new SqlSugarRepository<Sale>(); // 使用仓库实例的AsQueryable方法开始构建查询 var saleSummary = saleRepository.AsQueryable() // 使用LeftJoin方法连接Sale表和Product表,条件是两个表中的ProductId和Id字段相等 .LeftJoin<Product>((x, y) => x.ProductId == y.Id) // 根据Product的Name和Sale的SaleYear字段对连接后的结果进行分组 .GroupBy((x, y) => new { y.Name, x.SaleYear }) // 选择每个分组的产品名称(Name),销售年份(SaleYear)和该分组下所有记录的Amount字段之和(TotalSale) // SqlFunc.AggregateSum用于计算每个分组中Amount的总和,即总销售额 .Select((x, y) => new { y.Name, x.SaleYear, TotalSale = SqlFunc.AggregateSum(x.Amount) }) // 将之前的查询结果作为一个新的表进行处理 .MergeTable() // 将查询结果转换为列表 .ToList(); // 遍历查询结果列表 foreach (var item in saleSummary) { // 打印每个满足条件的产品的名称、销售年份和总销售额 Console.WriteLine($"{item.Name}\t{item.SaleYear}\t{item.TotalSale}"); } }

image.png

  1. 构建查询:首先,通过AsQueryable方法开始构建对Sale表的查询。
  2. 连接表格:使用LeftJoin方法连接Sale表和Product表,连接条件是Sale表中的ProductId字段与Product表中的Id字段相等。
  3. 分组:使用GroupBy方法按ProductNameSaleSaleYear对连接后的结果进行分组。
  4. 选择:通过Select方法选择每个分组的产品名称(Name)、销售年份(SaleYear)和总销售额(TotalSale),其中使用SqlFunc.AggregateSum来计算每个分组的销售总额。
  5. 合并表格MergeTable方法将之前的查询结果视为一个新的表,以便进行进一步的处理。
  6. 结果转换:使用ToList方法将查询结果转换为列表。
  7. 遍历和打印:最后,遍历查询结果列表,打印每个产品的名称、销售年份和总销售额。

通过上述例子,我们可以看到SqlSugar在处理分组查询时的灵活性和强大功能。无论是基本的分组聚合,还是分组后的筛选、排序,亦或是在连接查询结果上进行分组,SqlSugar都能提供简洁有效的解决方案。这使得开发者能够轻松应对复杂的业务需求,提高开发效率。

本文作者:技术老小子

本文链接:

版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!