一、分组查询和使用

1.1 语法

只有在聚合对象需要筛选的时候才会用到Having,一般分组查询用不到可以去掉

  var list = db.Queryable<Student>()
             .GroupBy(it => new { it.Id, it.Name }) //可以多字段
             .Where(it=>it.Id>0)//普通过滤
             //.Having(it => SqlFunc.AggregateAvg(it.Id) > 0)//聚合函数过滤
             .Select(it => new 
                          idAvg = SqlFunc.AggregateAvg(it.Id??0),
                          count = SqlFunc.AggregateCount(it.Id),  
                           name = it.Name })
             .ToList();
              
//      SELECT     
//           AVG([Id]) AS[idAvg], 
//           [Name] AS[name]  
//               
//               FROM[Student] GROUP BY[Name],[Id] Where Id > 0 
 
//Count用法
//SqlFunc.AggregateCount(it.Id)
 
 
//单个字段用法  (多个单个也能叠加)
  .GroupBy(it =>SqlFunc.SubString(it.Name,0,1))
  .GroupBy(it =>it.Id)
   
//新版本支持了分组带函数
  .GroupBy(it=>new { it.Id, name= SqlFunc.ToString(it.Name) }

分组查询可以 进行汇总查询 、平均值、最大、最小等操作

1.2  去null(isnull或ifnull)

库中存在null如果不处理那么avg和sum将查询不了数据

SqlFunc.AggregateSumNoNull(it.num) //等于 sum(isnull(num,0))
//5.1.4.108-preview31+
SqlFunc.AggregateAvgNoNull(it.num) //等于 avg(isnull(num,0))
 
//nullable类型也可以用??去除null
SqlFunc.AggregateSum(it.num??0)// avg(isnull(num,0))
  
//原始用法
SqlFunc.AggregateSum(SqlFunc.Isnull(it.num,0))// avg(isnull(num,0))

1.3 排序统计列

  var list = db.Queryable<Student>()
             .GroupBy(it => new { it.Id, it.Name })  
             .Where(it=>it.Id>0) 
             .Select(it => new 
                          idAvg = SqlFunc.AggregateAvg(it.Id??0),
                          count = SqlFunc.AggregateCount(it.Id),  
                           name = it.Name })
             .MergeTable()//需要加MergeTable才能排序统计过的列
             .OrderBy(it=>it.count)
             .ToList();

二、Distinct使用

一般用来指定字段去重复,查询不重复的值,去重字段

var list = db.Queryable<Student>().Distinct().Select(it => new { it.Name }).ToList();
//SELECT  DISTINCT  [Name] AS [Name]  FROM [STudent]

注意:升级较新版本兼容了rownumber冲突

三、分组获取第一条(或几条)

3.1 所有数据库通用写法

var list=db.Queryable<Order>() 
                .GroupBy(it => it.Name)//MergeTable之前不要有OrderBy
                .Select(it => new
                {
                    name = it.Name,
                    id = SqlFunc.AggregateMax(it.Id)
                })
                .MergeTable()
                .LeftJoin<Order>((a, b) => a.id == b.Id)
                 //OrderBy((a,b)=a.Id)
                .Select((a, b) => b).ToList();
// SELECT [b].* 
//  FROM  
//  (SELECT*FROM(SELECT [Name]AS[name],MAX([Id]) AS [id] FROM [Order] GROUP BY [Name]) MergeTable )[a]
//  Left JOIN 
//  [Order] [b]  ON ( [a].[id] = [b].[Id] )

该写法只能支持获取1条,如果想分组获取1条以上看 标题2

3.2. 开窗函数语法实现(较多库支持)

新版本才支持  5.1.1

支持数据库:SqlServer、MySql8.0+、Oracle 、PgSql、达梦、金仓 等数据库支持

说明: partition by name 就等于  group by name

var test48 = db.Queryable<Order>().Select(it => new
            {
                index2 = SqlFunc.RowNumber(it.Id,it.Name),//order by id partition by name
                //多字段排序  order by id asc ,name desc
                //SqlFunc.RowNumber($"{it.Id} asc ,{it.Name} desc ",$"{it.Name}")
                price=it.Price,
                date=it.CreateTime
            })
            .MergeTable()//将结果合并成一个表
            .Where(it=>it.index2==1) //相同的name只取一条记录
            //前20条用Where(it=>it.index2=<=20) 
           .ToList();
            
//SELECT * FROM  
       // (SELECT  
            //row_number() over( partition by [Name] order by [Id]) AS [index2], 
            //[Price] AS [price] , 
            //[CreateTime] AS [date]  FROM [Order]
        // ) MergeTable   WHERE ( [index2] = 1 )
 
//多个字段 5.1.2-preview01
SqlFunc.RowNumber($"{it.Id} asc ,{it.Name} desc "  , $"{it.Id},{it.Name}")
//partition by [id],[Name] order by [Id] asc,[name] desc

3.3 个别数据库写法

1.个别库独有实现
像Oracle 、SqlServer 语法糖
db.Queryable<Order>().Take(1).PartitionBy(it=>it.Name).ToList()
db.Queryable<Order>().OrderBy(it=>it.id,OrderByType.Desc).Take(1).PartitionBy(it=>it.Name).ToList()

四、特殊日期分组

例子1 :  年月分好组简写

var students = db.Queryable<Order>()
    .GroupBy(it=>it.CreateTime.ToString("yyyy-MM"))
    .Select(it=>new 
        Time=it.CreateTime.ToString("yyyy-MM"),
        Count=SqlFunc.AggregateCount(it.name)
             
    })
    //如果想在后面OrderBy
    //.MergeTable().OrderBy(it=>it.Count)
    .ToList();

例子2: 根据年月日进行分组

var getOrderBy = db.Queryable<Order>().Select(it=>new  {
                 Id=it.Id,
                 Name=it.Name,//这儿不能写聚合函数,因没分组
                 CreateTime=it.CreateTime.Date//只取日期
             })
            .MergeTable()//将查询结果转成一个表
            .GroupBy(it=>it.CreateTime)
            .Select(it=>new { id =SqlFunc.AggregateMax(it.Id),crate=it.CreateTime })
            .ToList();

例子3:使用SQL语句分组

.GroupBy(it => SqlFunc.MappingColumn(default(string), " CONVERT(varchar(10),t.F_OutTime, 120)"))
//生成的Sql如下
//GROUPBY CONVERT(varchar(10),t.F_OutTime, 120)

五、Count(distinct 字段)

db.Queryable<Order>().Select(it=>SqlFunc.AggregateDistinctCount(it.Id)).ToList()//最新版本支持
 
db.Queryable<Order>().Select<int>("count(distinct  id)").ToList();

六、强制不参数化

语法更新:

//新语法 5.1.4.64
SqlFunc.MappingColumn<string>("'a'"//生成的Sql是 'a'  ,不会是参数化对象
SqlFunc.MappingColumn<int>("1"//生成的Sql是1
 
//老版本语法
SqlFunc.MappingColumn(default(string),"'a'")
SqlFunc.MappingColumn(default(int),"1")

一般解决GroupBy参数名不同引起的分组失败

例如:Group里面是参数@p1=1  Select中是参数 @p2 =1  ,只因参数名不同引起了分组失败

//改之前
var list = db.Queryable<Order>()
    .GroupBy(it =>it.Name.Substring(0,1))
    .Select(it => new {
            name=it.Name.Substring(0,1))
        })
.First();
 
//改之后
var list = db.Queryable<Order>()
    .GroupBy(it =>
        it.Name.Substring( SqlFunc.MappingColumn<int>("0"),
                  SqlFunc.MappingColumn<int>("1")))
                             
        .Select(it => new {
            name=it.Name.Substring(
                  SqlFunc.MappingColumn<int>("0"),
                   SqlFunc.MappingColumn<int>("1"))
        })
.First();
 
//这样生成的Sql就不会有参数化对象了
//SELECT  SUBSTRING(`Name`,1 + 0,1) AS `name`  FROM `Order`   
// GROUP BY SUBSTRING(`Name`,1 + 0,1)   LIMIT 0,1

七、联表中GroupBy用法

 db.Queryable<Student>()
       .LeftJoin<Book>((it,b)=>it.id==b.studentid)
       .GroupBy((it,b)=> new { it.Id, it.Name }) //可以多字段
       .Having((it,b)=> SqlFunc.AggregateAvg(it.Id) > 0)//不是聚合函数用Where就可以了
       .Select((it,b)=> new {idAvg=SqlFunc.AggregateAvg(it.Id),name=it.Name})//Select写最后
       .ToList();
 
        //GroupBy用到b表那就应该写成 (it,b)=>new {}
        //没用到b表可以写成这样  it=>new{}

联表查询用法:https://www.donet5.com/Home/Doc?typeId=1185

八、分组取ID+集合的方式(ef类似)

请升级到 5.1.4.66

 //List<T>集合
 var list = db.Queryable<Order>()
           .Where(it=>it.Id>0)
          .GroupBy(it=>it.CustomId)//根据CustomId分组
          .Select(it => new {
               cusid=it.CustomId,
               list=SqlFunc.Subqueryable<Order>().Where(s=>s.CustomId==it.CustomId).ToList()
           }).ToList();
            
 //List<string>集合          
 var list = db.Queryable<Order>()
           .Where(it=>it.Id>0)
          .GroupBy(it=>it.CustomId)//根据CustomId分组
          .Select(it => new {
               cusid=it.CustomId,
               ids=SqlFunc.Subqueryable<Order>().Where(s=>s.CustomId==it.CustomId).ToList(s=>s.Id)
           }).ToList();

九、所有开窗口函数

是group的高级应用 ,他不依赖group可以分组,并且可以多个使用而不需写group

  count = SqlFunc.RowCount(),// count (1) over() 
  max= SqlFunc.RowMax(it.num??0),// max(isnull(num,0)) over() 
  min= SqlFunc.RowMin(it.num??0),// min(isnull(num,0)) over() 
  avg= SqlFunc.RowAvg(it.num??0),// avg(isnull(num,0)) over() 
  index = SqlFunc.RowNumber(it.Id), // row_number() over( order by a.`Id`)
  index = SqlFunc.RowNumber(it.Id,it.Name)//  row_number() over( partition by name order by a.`Id`)
   index = SqlFunc.RowNumber(SqlFunc.Desc(it.Id),it.Name)//  row_number() over( partition by name order by a.`Id` desc)
   //多字段看3.1

十、Count加条件

通过sum加三元实现Count加条件统计,Sum(1)等于同Count, 只把不想的改成0这样Sum就是统计的想要的

  var list = db.Queryable<Student>()
             .GroupBy(it => new { it.Name  }) 
             .Select(it => new 
                          count= SqlFunc.AggregateSum(it.Id>10?1:0),
                         })
             .ToList();

十一、不分组使用Count

更多看标题9

 count = SqlFunc.RowCount(),// count (1) over()

SqlSugar分组查询的更多相关文章

  1. MySQL时间分组查询

    表TESTER 字段:id -- INT    date  -- TIMESTAMP 1.如何按年.月.日分组查询? select DATE_FORMAT(date,'%Y-%m-%d') time, ...

  2. 关系数据库SQL之基本数据查询:子查询、分组查询、模糊查询

    前言 上一篇关系数据库常用SQL语句语法大全主要是关系型数据库大体结构,本文细说一下关系型数据库查询的SQL语法. 语法回顾 SELECT [ALL|DISTINCT] <目标列表达式>[ ...

  3. Hibernate 分组查询 子查询 原生SQL

    分组查询: 使用group by关键字对数据分组,使用having关键字对分组数据设定约束条件,从而完成对数据分组和统计 1.1 聚合函数:常被用来实现数据统计功能 ① count() 统计记录条数 ...

  4. mysql 分组查询问题 group_concat

    这几天在做购物车的时候.购物车内的商品为一个商品占一行,结果再从数据库读出的时候,没有分组,而是循环所有的内容出来,然后进行判断.如果一样的话就把他保存到一个变量中.但是自己逻辑没搞清楚.一直出bug ...

  5. mongodb 分组查询

    数据的保存 include_once 'mDB.class.php'; $m=new mDB(); $m->setDB('mydb'); // $m->save('stu',['dept' ...

  6. 08章 分组查询、子查询、原生SQL

    一.分组查询 使用group by关键字对数据分组,使用having关键字对分组数据设定约束条件,从而完成对数据分组和统计 1.1 聚合函数:常被用来实现数据统计功能 ① count() 统计记录条数 ...

  7. Mongodb for C# 分组查询

    #region 排序获取集合 static List<BsonDocument> GetPagerWithGroup(string connectionString, string dat ...

  8. SQL分组查询group by

    注意:select 后的字段,必须要么包含在group by中,要么包含在having 后的聚合函数里. 1. GROUP BY 是分组查询, 一般 GROUP BY 是和聚合函数配合使用 group ...

  9. SQL group by分组查询(转)

    本文导读:在实际SQL应用中,经常需要进行分组聚合,即将查询对象按一定条件分组,然后对每一个组进行聚合分析.创建分组是通过GROUP BY子句实现的.与WHERE子句不同,GROUP BY子句用于归纳 ...

  10. mongodb使用mongoose分组查询

    一个分组查询的例子: model.aggregate([{$match: ops}, {$unwind: '$details'}, {$sort: {create_at: -1}}, { $group ...

随机推荐

  1. Linux系统用户态和内核态

    Unix/Linux的体系架构 如上图所示,从宏观上来看,Linux操作系统的体系架构分为用户态和内核态(或者用户空间和内核空间).内核从本质上看是一种软件-----控制计算机的硬件资源,并提供上层应 ...

  2. AliPLC 智能丢包补偿算法,提升弱网环境的通话质量

    在线视频/语音通话逐渐成为人们日常生活的一部分,而复杂多变的网络环境会导致部分音频包无法传送到接收端,造成语音信号的短时中断或者卡顿,这会严重影响通话体验,为解决这类问题,阿里云视频云音频技术团队在综 ...

  3. # 2027 ( 统计元音 ) :hash应用

    Problem Description 统计每个元音字母在字符串中出现的次数. Input 输入数据首先包括一个整数n,表示测试实例的个数,然后是n行长度不超过100的字符串. Output 对于每个 ...

  4. 【每日一题】23.Removal (计数DP)

    补题链接:Here 计数DP讲解:Here 这是一个计数类的dp dp[i][j]表示前i个数字中,删除j个元素的方案数 很容易得到转移方程:\(f[i][j] = f[i - 1][j - 1] + ...

  5. Codeforces Round #707 (Div. 2, based on Moscow Open Olympiad in Informatics Editorial

    Codeforces Round #707 (Div. 2, based on Moscow Open Olympiad in Informatics) Problem 1501A. Alexey a ...

  6. 🚀Flutter应用程序的加固原理

    ​ 在移动应用开发中,Flutter已经成为一种非常流行的技术选项,可以同时在Android和iOS平台上构建高性能.高质量的移动应用程序.但是,由于其跨平台特性,Flutter应用程序也面临着一些安 ...

  7. Blazor开发小游戏?趁热打铁上!!!

    大家好,我是沙漠尽头的狼. 网站使用Blazor重构上线一天了,用Blazor开发是真便捷,空闲时间查查gpt和github,又上线一个 正则表达式在线验证工具 和几个在线小游戏,比如 井字棋游戏.扫 ...

  8. 如果诸葛亮会编程,用Java写出师表...

    继上一篇 "如果诸葛亮用C#写出师表..."后,站长想自己的第一语言是Java,虽然平时工作上用的不多,也用Java实现一遍吧,改改就是了,无非就是: C#的Console.Wri ...

  9. AHB2APB设计

    AHB2APB Bridge位置 AHB子系统时钟在200Mhz左右,APB时钟在几十Khz到几十Mhz 所以要进行跨时钟域处理,从AHB高时钟频率转到APB低时钟频率 AHB2APB Bridge规 ...

  10. Nginx 配置文件备忘单

    Nginx 是用于 Web 服务.反向代理.缓存.负载平衡.媒体流等的开源软件.在这篇文章中,我将提到一些我们经常使用的 Nginx 配置. 监听端口 server { Standard HTTP P ...