FreeSql学习笔记——7.分组聚合
前言
分组就是将元数据通过某些条件划分为组,而聚合就是对这些组进行整合操作;在sqlserver数据库中使用的关键字group by使符合条件的集合通过某些字段分好组,再使用聚合函数(如max()、mix())整合结果集;
FreeSql的聚合分组与数据库命名一样,分组使用GroupBy(),配合Sum()、Max()、Min()等聚合方法进行聚合分组;
GroupBy分组聚合
根据姓名分组(添加数据的时候使用了xx1,xx2这样的命名)后,使用Having()方法排除了记录数小于等于1的记录,并根据记录数进行了倒叙,查询了姓名和数量。
_freeSql.Select<Student>()
.GroupBy(x => new { Name = x.Name.Substring(0, 2) })
.Having(x => x.Count() > 1)
.OrderByDescending(x => x.Count())
.ToList(x => new { x.Key.Name, Count = x.Count() });
//[{"Name":"小明","Count":10},{"Name":"小红","Count":2}]
//SELECT substring(a.[Name], 1, 2), count(1) as1
//FROM[Student] a
//GROUP BY substring(a.[Name], 1, 2)
//HAVING(count(1) > 1)
//ORDER BY count(1) DESC
ToAggregate聚合
官方推荐另一种不分组求聚合值的方法,就是使用 ToAggregate 替代 ToList
_freeSql.Select<Student>()
.Where(x => x.Age > 5)
.Aggregate(x => x.Avg(x.Key.Age), out var age);
//SELECT avg(a.[Age]) as1
//FROM [Student] a
//WHERE (a.[Age] > 5)
//结果为age的值
踩个坑
如果使用这个写法会发生什么呢?
_freeSql.Select<Student>()
.Aggregate(x => new { count = x.Count(), sum = x.Sum(x.Key.Age) }, out var res)
.Where(x => x.Age > 5)
.ToList();
前面说过ToAggregate 是代替ToList的,也就是说首先会去算一下记录数、和,赋值给变量res,然后再使用Age>5的条件去查一次数据,sql如下
SELECT count(1) as1, sum(a.[Age]) as2
FROM [Student] a
SELECT a.[Id], a.[Name], a.[Age], a.[Status], a.[AddTime], a.[Remark], a.[Version], a.[ClassId]
FROM [Student] a
WHERE (a.[Age] > 5)
所以上面的写法会造成两次查询,一次是执行Aggregate(),一次是执行ToList(),由于执行Aggregate()的时候没有条件,所以结果为全表的Count()、Sum(),将Aggregate()使用,就好理解了
如果需要查询数据集,又要聚合查询,可以将Where提到前面,这样聚合也就有了条件;
_freeSql.Select<Student>()
.Where(x => x.Age > 5)
.Aggregate(x => new { count = x.Count(), sum = x.Sum(x.Key.Age) }, out var res)
.ToList();
//SELECT count(1) as1, sum(a.[Age]) as2
//FROM [Student] a
//WHERE (a.[Age] > 5)
//SELECT a.[Id], a.[Name], a.[Age], a.[Status], a.[AddTime], a.[Remark], a.[Version], a.[ClassId]
//FROM [Student] a
//WHERE (a.[Age] > 5)