SqlSugar是一个轻量级但功能强大的.NET ORM框架,它提供了丰富的查询功能,包括灵活的分组查询操作。分组查询是数据库操作中常见的需求之一,用于将数据集合按照某个或某些字段进行分组,并对每个组进行聚合运算。在本文中,我们将通过几个例子探讨如何使用SqlSugar进行分组查询。
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; }
}
在这个类中,SugarTable和SugarColumn是SqlSugar提供的特性,用于映射实体类到数据库的表和列。IsPrimaryKey标记该字段为主键,IsIdentity表示该字段是自增的。
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实体类中,我们同样使用SugarTable和SugarColumn特性来定义与数据库表和列的映射。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}");
}

如果要根据多个字段进行分组,例如根据CategoryId和SaleYear分组,并计算每组的销售总额,可以这样做:
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}");
}
}

分组聚合后,我们可能需要对结果进行筛选,比如找出销售总额超过一定值的分组。
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}");
}
}
AsQueryable方法开始构建对Sale表的查询。GroupBy方法按ProductId和SaleYear对记录进行分组。Select方法选择每个分组的ProductId、SaleYear和TotalSale(总销售额),其中使用SqlFunc.AggregateSum来计算每个分组的销售总额。MergeTable方法将之前的查询结果视为一个新的表,以便进行进一步的处理。Where方法从新表中筛选出总销售额超过10000的记录。ToList方法将查询结果转换为列表。对分组聚合的结果进行排序,例如按销售总额降序排列。
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}");
}
}

AsQueryable方法开始构建对Sale表的查询。LeftJoin方法连接Sale表和Product表,连接条件是Sale表中的ProductId字段与Product表中的Id字段相等。GroupBy方法按Product的Name和Sale的SaleYear对连接后的结果进行分组。Select方法选择每个分组的产品名称(Name)、销售年份(SaleYear)和总销售额(TotalSale),其中使用SqlFunc.AggregateSum来计算每个分组的销售总额。MergeTable方法将之前的查询结果视为一个新的表,以便进行进一步的处理。ToList方法将查询结果转换为列表。通过上述例子,我们可以看到SqlSugar在处理分组查询时的灵活性和强大功能。无论是基本的分组聚合,还是分组后的筛选、排序,亦或是在连接查询结果上进行分组,SqlSugar都能提供简洁有效的解决方案。这使得开发者能够轻松应对复杂的业务需求,提高开发效率。
本文作者:技术老小子
本文链接:
版权声明:本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!