1、基础教程

1.1 API目录

*****只查一列*****
//First: SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id)      
//max例1: SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Max(s => s.Id)
//max例2: SqlFunc.Subqueryable<School>()..Where(s=>s.Id==st.Id).Select(s=>SqlFunc.AggregateMax(s.Id))      
//min:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Min(s => s.Id)
//avg:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Avg(s => s.Id)
//count:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Count()
//sum:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Sum(s => s.num)
//去重后汇总数量
//SqlFunc.Subqueryable<School>().Where(s => z.Id == st.Id).Select(s=>SqlFunc.AggregateDistinctCount(s.Name))
//逗号分割列 
//SqlFunc.Subqueryable<Order>().Where(z=>z.Id==it.Id).SelectStringJoin(z => z.Name, ",")
//完整用例:看标题8
  
  
*****返回List或者实体*****
新功能:5.1.3.36
//SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList()
//SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList(it=>new Class(){ Name=it.Name})
//更多看标题4
 
 
*****返回单个实体*****
//SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).First() 
//更多看标题9
 
 
*****IN、Not in、Exists、Not Exists*****
//看标题2

1.2 where中使用

var getAll = db.Queryable<Student, School>((st, sc) => new JoinQueryInfos(JoinType.Left,st.Id==sc.Id) )
.Where(st => st.Id == SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id))
.ToList();
      
/*生成的MYSQL语句,如果是SqlServer就是TOP 1
SELECT `st`.`ID`,`st`.`SchoolId`,`st`.`Name`,`st`.`CreateTime` 
     FROM `STudent` st Left JOIN `School` sc ON ( `st`.`ID` = `sc`.`Id` )  
      WHERE ( `st`.`ID` =(SELECT `Id` FROM `School` WHERE ( `Id` = `st`.`ID` ) limit 0,1))
*/

1.3 在select中使用

var getAll = db.Queryable<Student, School>((st, sc) => new JoinQueryInfos(JoinType.Left,st.Id==sc.Id ))
.Select(st => new{
          name = st.Name,
          id = SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id)
       }).ToList();

2、IN和NOT IN的操作

2.1 Exists

Exists 和 in 区别在于 Exists 扩展性更强,支持多个字段 (简单的说In能实现的Exists都能实现)

//等同于IN
var getAll7 = db.Queryable<Student>()
.Where(it => SqlFunc.Subqueryable<School>().Where(s =>s.Id==it.Id).Any()).ToList();
 
/*生成的SQL(等于同于it.id in(select id from school)只是写法不一样
SELECT `ID`,`SchoolId`,`Name`,`CreateTime` FROM `STudent` it 
WHERE (EXISTS ( SELECT * FROM `School` WHERE ( `Id` = `it`.`ID` ) )) 
*/
 
 
//等同于NOT IN
var getAll8 = db.Queryable<Student>().Where(it => 
SqlFunc.Subqueryable<School>().Where(s => s.Id == it.Id).NotAny()).ToList();
 
/*生成的SQL
SELECT `ID`,`SchoolId`,`Name`,`CreateTime` FROM `STudent` it  
WHERE (NOT EXISTS ( SELECT * FROM `School` WHERE ( `Id` = `it`.`ID` ) ))
*/
 
//搜索关键词:exits

2.2 In和 Not In (5.0.7.5)

在有GroupBy的情况下==自动转成 in

db.Queryable<Order>()
.Where(it=>it.Id==SqlFunc.Subqueryable<Custom>().GroupBy(z=>z.OrderId).Select(z=>z.OrderId)).ToList()
 
//Sql
//SELECT [Id],[Name] FROM [Order]  
// WHERE  [Id] in ((SELECT [OrderId] FROM [Custom] GROUP BY [OrderId]))

2.3 分页In

db.Queryable<Order>().In(it=>it.Id,db.Queryable<Order>().Skip(1).Take(100).Select(it=>it.Id)).ToList();

3、子查询中使用Sql

最新版本才支持

 string sql=" (select top 1 id from [Order] ) ";
 var list = db.Queryable<Order>()
               .Select(it => new
              {
                name=it.Name,
                customName= SqlFunc.MappingColumn<string>(sql)
                //老版本MappingColumn(default(string),sql) 
               }).ToList();
               //如果存在SQL拼接将SQL提取到外面在传进来,有些VS拼接会有问题

Sql代码如下:

SELECT  
          [NameAS [name] , 
          (select top 1 id from [Order] ) AS [customName] 
     FROM [Order]

4、ToList()集合对象

方式1:简单方式(5.1.3.38)

直接在Select中进行ToList ,

性能:   大于循环数倍  ,大部分情况性能小于ThenMapper方式和导航 ,写法简单性能也说的过去

//请升级到 5.1.3.36+ 
 db.Queryable<Order>()
 .Select(it => new
         {
           CustomId = it.CustomId,
           OrderId = it.Id,
           OrderName = it.Name,
           CustomList = SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList()
         })
        .ToList();
 //也可以DTO
 SqlFunc.Subqueryable<Custom>()
           .Where(c=> c.Id == it.CustomId).
            ToList(c=> new Class(){ Name=c.Name}) //转成DTO
 //注意:where  ToList里面 c 的别名要一致
  
  
//只查List<string>这种集合 
SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList(c=>c.Name)//最新版本
 
 
//自动DTO 5.1.4.70
SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList<DTO>()
SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).ToList(it=>new DTO(){},true);//和Queryable类似

方式2:性能、功能、跨库

该功能在同类框架中性能比较好不会生成垃圾SQL , 在现有结果进行一对多操作

var treeRoot=db.Queryable<Tree>().ToList();//可以联表查询,只要返回List中有关联字段就可以
 
//填充子对象 
//原理: 数据库一次读取 In (list[0].id,list[1].id,list[2].id...) 内存分配到对应Child
//所以无论集合多少条记录  ThenMapper 只会操作一次库  
db.ThenMapper(treeRoot, item =>
 {   
   //用例1:简单填充  
   //参数解释:子表的ParentId和主表的Id 进行关联查询(有Select写到SetContext前面)
   //可以额外加Where写SetContext前面,但是不能带有item对象,item要写SetContext里面
   item.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => item.Id, item).ToList();
     
    
   //用例2:可以多属性
   //item.Child=xxxx
   //item.Parent=xxxx
    
     
   //用例3:类型转换类转成DTO (注意:Select中的关联字段要赋值)
   //item.Child = db.Queryable<Tree>()
   //         .Select(it=>new ViewTree(){ParentId=x.ParentId,Id=i.Id,Name=it.Name }) 
   //         .SetContext(x => x.ParentId, () => item.Id, item).ToList();
    
   //用例4:联表填充
   //item.Child=db.Queryable<Tree>()
   //.LeftJoin<Tree>((i,y)=>i.ParentId==y.Id)
   //.Select((i,y)=>new viewmodel(){ Parentid=i.Parentid..........})
   //.SetContext(x => x.ParentId, () => item.Id, item).ToList();
 });
  
 
  
  
//异步
var treeRoot=await db.Queryable<Tree>().ToListAsync(); 
await db.ThenMapperAsync(treeRoot, async item =>
{   
   //给集合赋值  参数解释  子表的ParentId和主表的Id 进行关联查询
   item.Child =await db.Queryable<Tree>().SetContextAsync(x=>x.ParentId,()=>item.Id, item);
});
 
 
//无限层级
var treeRoot=db.Queryable<Tree>().Where(it => it.Id == 1).ToList();
//第一层
db.ThenMapper(treeRoot, item =>
{
    item.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => item.Id, item).ToList();
});
//第二层
db.ThenMapper(treeRoot.SelectMany(it=>it.Child), it =>
{
    it.Child = db.Queryable<Tree>().SetContext(x => x.ParentId, () => it.Id, it).ToList();
});
 
//跨库 
var mydb=db.GetConnection(1);
mydb.ThenMapper(root,item=>{...});

方式3:导航方式

这种已经不属于子查询了,属于另一个查询体系,详细功能:

https://www.donet5.com/Home/Doc?typeId=1188

5、子查询在Join

5.0.5.4+

var list = db.Queryable<Order>().Where(it =>
            SqlFunc.Subqueryable<A>() 
             .LeftJoin<B>((i,y)=>i.ItemId==y.ItemId)
             .InnerJoin<C>((i,y,z) => i.ItemId == z.ItemId)
             .Where((i,y,z)=>i.ItemId==1)
              .Any()
            ).ToList();
//新版本支持了Subquery.join使用 Where<T1,T2>((x,y)=> x.id==y.id)

6、子查询使用别名

如果点不出AS请升级

SqlFunc.Subqueryable<A>().AS("A01")  //这样查询的就是 A01表

7、字符串拼接

5.1.1-preview14 逗号拼接

 //sqlerver : FOR XML PATH
 //mysql sqlite : group_concat
 //oracle : listagg
 //pgsql  :string_agg
 var list= db.Queryable<Order>()
   .Select(it => new
            
             //names="名字1,名字2,名字3"
              names=SqlFunc.Subqueryable<custom>().
                               Where(z=>z.oid==it.id)
                               .SelectStringJoin(z => z.Name, ",")
            })
           .ToList();
//多字段 不能有null相加 , 字段有null需要加上 z.Name??""
.SelectStringJoin(z => SqlFunc.MergeString(z.Name,"-",z.Id.ToString()), ",")

8、只查一列 (top 1)

//First:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Select(s => s.Id)        
//max例1:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Max(s => s.Id)
//max例2:SqlFunc.Subqueryable<School>().Where(s=>s.Id==st.Id).Select(s=>SqlFunc.AggregateMax(s.Id))       
//min:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Min(s => s.Id)
//avg:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Avg(s => s.Id)
//count:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Count()
//sum:SqlFunc.Subqueryable<School>().Where(s => s.Id == st.Id).Sum(s => s.num)
//去重后汇总数量
//SqlFunc.Subqueryable<School>().Where(s => z.Id == st.Id).Select(s=>SqlFunc.AggregateDistinctCount(s.Name))
//逗号分割列 
//SqlFunc.Subqueryable<Order>().Where(z=>z.Id==it.Id).SelectStringJoin(z => z.Name, ",")
 
 
//用例
Select(it=>
    new
     id=it.id,
     schoolname=SqlFunc.Subqueryable<School>().Where(s=>s.Id==it.ShoolId).Select(s=>s.Name)  
     //对应的Sql:  
     //schoolname=(SELECT `Name` FROM `School` `s` WHERE (`s`.`Id`=`it`.`ShoolId`)limit 0,1)
   })
    
//如果要查整个对象:看标题9

9、子查询 First()整个对象

//需要升级5.1.4.59
var list= db.Queryable<Order>()
 .Select(it => new
         {
           CustomId = it.CustomId,
           OrderId = it.Id,
           OrderName = it.Name,
           CustomList = SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).First()
         })
        .ToList();
//可以转DTO       
SqlFunc.Subqueryable<Custom>().Where(c => c.Id == it.CustomId).First(c=>new xxx(){ yy=c.id })
 
//如果只查一个字段:标题8

SqlSugar子查询的更多相关文章

  1. 深入理解MySql子查询IN的执行和优化

    IN为什么慢? 在应用程序中使用子查询后,SQL语句的查询性能变得非常糟糕.例如: SELECT driver_id FROM driver where driver_id in (SELECT dr ...

  2. Mysql - 性能优化之子查询

    记得在做项目的时候, 听到过一句话, 尽量不要使用子查询, 那么这一篇就来看一下, 这句话是否是正确的. 那在这之前, 需要介绍一些概念性东西和mysql对语句的大致处理. 当Mysql Server ...

  3. 在SQL Server中为什么不建议使用Not In子查询

        在SQL Server中,子查询可以分为相关子查询和无关子查询,对于无关子查询来说,Not In子句比较常见,但Not In潜在会带来下面两种问题: 结果不准确 查询性能低下       下面 ...

  4. 读书笔记--SQL必知必会11--使用子查询

    11.1 子查询 查询(query),任何SQL语句都是查询.但此术语一般指SELECT语句. SQL还允许创建子查询(subquery),即嵌套在其他查询中的查询. 作为子查询的SELECT语句只能 ...

  5. 你真的会玩SQL吗?无处不在的子查询

    你真的会玩SQL吗?系列目录 你真的会玩SQL吗?之逻辑查询处理阶段 你真的会玩SQL吗?和平大使 内连接.外连接 你真的会玩SQL吗?三范式.数据完整性 你真的会玩SQL吗?查询指定节点及其所有父节 ...

  6. Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等)

    Linq to SQL 语法查询(链接查询,子查询 & in操作 & join,分组统计等) 子查询 描述:查询订单数超过5的顾客信息 查询句法: var 子查询 = from c i ...

  7. 当没有用 EXISTS 引入子查询时,在选择列表中只能指定一个表达式。

    当没有用 EXISTS 引入子查询时,在选择列表中只能指定一个表达式.比如 select * from T_Employee where FNumber not in ( select top 5*  ...

  8. Oracle学习笔记五 SQL命令(三):Group by、排序、连接查询、子查询、分页

    GROUP BY和HAVING子句 GROUP BY子句 用于将信息划分为更小的组每一组行返回针对该组的单个结果 --统计每个部门的人数: Select count(*) from emp group ...

  9. [转]HQL中的子查询

    原文地址:http://blog.csdn.net/xb12369/article/details/8638683 子查询:   子查询是SQL语句中非常重要的功能特性,它可以在SQL语句中利用另外一 ...

  10. MySQL 子查询与连接操作笔记

    SQL语句之间是可以进行连接操作的,在一些复杂的数据操作中必须用到连接操作.简单的说就是一个SQL语句的结果可以作为相连接的SQL操作的一部分.SQL结构化查询语句,子查询是指的所有的SQL操作,并非 ...

随机推荐

  1. 多线程 ThreadPoolTaskExecutor 应用

    1.如何判断线程池所有任务是否执行完毕 package com.vipsoft.web; import org.junit.jupiter.api.Test; import org.slf4j.Log ...

  2. Hadoop面试题(一)

    1.集群的最主要瓶颈 磁盘IO 2.Hadoop运行模式 单机版.伪分布式模式.完全分布式模式 3.Hadoop生态圈的组件并做简要描述 1)Zookeeper:是一个开源的分布式应用程序协调服务,基 ...

  3. 【HZERO】定时任务

  4. 从0开发3D引擎(十三):使用领域驱动设计,从最小3D程序中提炼引擎(第四部分)

    目录 上一篇博文 下一篇博文 本文流程 回顾上文 解释基本的操作 如何在浏览器上运行index.html 开始实现 准备 建立代码的文件夹结构,约定模块文件的命名规则 模块文件的命名原则 一级和二级文 ...

  5. uni-app安卓手机无法连接到调试服务

    uni-app连接安卓真机,发现接口调不通,打开Hbuilder下方的调试.可查看失败原因:如下图 解决方法:电脑变热点,手机连这个热点,就能解决手机和pc在同一局域网.具体操作,参照以下网站: ht ...

  6. C#爬虫知识介绍

    爬虫 爬虫(Web Crawler)是指使用程序自动获取互联网上的信息和数据的一种技术手段.它通常从一个起始网址出发,按照一定的规则递归地遍历网页,并将有用的信息提取出来,然后存储到本地或者数据库中, ...

  7. java基础(15)--多态

    一.多态的含义 1.多种形态.多种状态,指的是编译与运行有不同的状态 2.编译时->静态绑定 3.执行时->动态绑定 4.多类典型场景:父类的引用指向了子类型的对象   二.向下转型与向上 ...

  8. 关于编写C时的调试--VS,VSCODE,DEV-C++

    1.问题 VS最大的问题是不支持scanf函数,后面的调试部分我就没试了,主要用VS来写C++ VSCODE是服了他的C/C++插件,我死活卡在debug中scanf的输入部分,集成终端根本无法输入, ...

  9. 类外static函数定义要不要加static关键字?

    类外static函数定义要不要加static关键字? 先说答案:不需要. 错误代码: #include<iostream> #include<memory> using nam ...

  10. Net Core中使用EF Core连接Mysql数据库

    Entity Framework Core的前身是微软提供并主推的ORM框架,简称EF,其底层是对ADO.NET的封装.EF支持SQLServer.MYSQL.Oracle.Sqlite等所有主流数据 ...