今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊。看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了。我从简单到复杂地写,希望高手们不要见笑。下面的sql语句设计到三个表,表的内容我用txt文件复制进去,这里不妨使用上一个随笔介绍的建立端到端的package的方法将这些表导入到数据库中,具体的就不说了。

简单的聚合

从orders表中选择各个年份共有共有多少客户订购了商品第一种写法,我们可以写成这样

1selectYEAR(o.orderdate) orderyear,COUNT(distinct(custid)) numCusts2fromSales.Orders o3groupbyYEAR(o.orderdate)4go要注意的是如果把group by YEAR(o.orderdata)换成group by orderyear就会出错,这里涉及到sql语句的执行顺序问题,有时间再了解一下

第二种写法,

1selectorderyear,COUNT(distinct(custid))numCusts2from(selectYEAR(orderdate)asorderyear,custidfromsales.orders)asD3groupbyorderyear4go在from语句中先得到orderyear,然后再select语句中就不会出现没有这个字段的错误了

第三种写法,

1selectorderyear,COUNT(distinct(custid)) numCusts2from(selectYEAR(orderdate),custidfromsales.orders)asD(orderyear,custid)3groupbyorderyear4go在as D后面加上选择出的字段,是不是更加的清楚明了呢!

第四种写法,with出场了

1withcas(2selectYEAR(orderdate) orderyear, custidfromsales.orders)3selectorderyear,COUNT(distinct(custid)) numCustsfromcgroupbyorderyear4gowith可以使语句更加的经凑,下面是权威解释。

指定临时命名的结果集,这些结果集称为公用表表达式 (CTE)。该表达式源自简单查询,并且在单条 SELECT、INSERT、UPDATE、MERGE 或 DELETE 语句的执行范围内定义。该子句也可用在 CREATE VIEW 语句中,作为该语句的 SELECT 定义语句的一部分。公用表表达式可以包括对自身的引用。这种表达式称为递归公用表达式。

----MSDN第五种写法,也可以借鉴第三种写法,这样使语句更加清楚明了,便于维护

1 withc(orderyear,custid)as(2 selectYEAR(orderdate),custidfromsales.orders)3 selectorderyear,COUNT(distinct(custid)) numCustsfromcgroupbyc.orderyear4 go上面5中写法都得到相同的结果,如下图1:

图1

添加计算现在要求要求计算出订单表中每年比上一年增加的客户数目,这个稍微复杂

1 withyearcountas(2 selectYEAR(orderdate) orderyear,COUNT(distinct(custid)) numCustsfromsales.ordersgroupbyYEAR(orderdate))3 selectcur.orderyear curyear,cur.numCusts curNumCusts,prv.orderyear prvyear,prv.numCusts prvNumCusts,cur.numCusts-prv.numCusts growth4 fromyearcount curleftjoinyearcount prvoncur.orderyear=prv.orderyear+15 go这里两次使用到with结果集。查询得到的结果如下图2

图2

复杂的计算查找客户id,这些客户和所有来自美国的雇员至少有一笔交易记录,查询语句如下

1 withTheseEmployeesas(2 selectempidfromhr.employeeswherecountry='USA'),3 CharacteristicFunctionsas(4 selectcustid,5 casewhencustidin(selectcustidfromsales.ordersasowhereo.empid=e.empid)then1else0endascharfun6 fromsales.customersasccrossjoinTheseEmployeesase)7 selectcustid,min(charfun)fromCharacteristicFunctionsgroupbycustidhavingmin(charfun)=18 go这里嵌套with语句,第with语句查找美国雇员的id,第二个语句使用这个结果和拥有客户的客户id和拥有关系标识做笛卡尔积运算。最后从这个笛卡尔积中通过标识找到最终的custid。

结果如下图3

图3

这里只有简单地介绍,没有深入,高手们不要见笑啊。



---------------------------------------------------------分界线----------------------------------------------------------

with语句和子查询的性能比较

在博友SingleCat的提醒下,对with语句做一些性能测试,这里使用的测试工具是SQL Server Profile。我选择了最后一个语句,因为这个语句比较复杂一点。开始的时候单独执行一次发现他们的差别不大,就差几个毫秒,后来想让他们多执行几次,连续执行10

次看看执行的结果。下面贴出测试用的语句。

1 /*with查询*/2 declare@withqueryvarchar(5000)3 declare@execcountint=04 set@withquery='with TheseEmployees as(5 select empid from hr.employees where country=N''USA''),6 CharacteristicFunctions as(7 select custid,8 case when custid in (select custid from sales.orders as o where o.empid=e.empid) then 1 else 0 end as charfun9 from sales.customers as c cross join TheseEmployees as e)10 select custid from CharacteristicFunctions group by custid having min(charfun)=1 order by custid11 '12 while@execcount<1013 begin14 exec(@withquery);15 set@execcount=@execcount+116 end17 18 /*子查询*/19 declare@subqueryvarchar(5000)20 declare@execcountint=021 set@subquery='select custid from Sales.Orders where empid in22 (select empid from HR.Employees where country = N''USA'') group by custid23 having count(distinct empid)=(select count(*) from HR.Employees where country = N''USA'');24 '25 while@execcount<1026 begin27 exec(@subquery);28 set@execcount=@execcount+129 end

从SQL Server Profile中截图如下

从图中可以看到子查询语句的执行时间要少于with语句,我觉得主要是with查询中有一个cross join做了笛卡尔积的关系,于是又实验了上面的那个简单一点的,下面是测试语句。

1 /*with语句*/2 declare@withqueryvarchar(5000)3 declare@execcountint=04 set@withquery='with c(orderyear,custid) as(5 select YEAR(orderdate),custid from sales.orders)6 select orderyear,COUNT(distinct(custid)) numCusts from c group by c.orderyear'7 while@execcount<1008 begin9 exec(@withquery);10 set@execcount=@execcount+111 end12 13 /*子查询*/14 declare@subqueryvarchar(5000)15 declare@execcountint=016 set@subquery='select orderyear,COUNT(distinct(custid)) numCusts17 from (select YEAR(orderdate),custid from sales.orders) as D(orderyear,custid)18 group by orderyear'19 while@execcount<10020 begin21 exec(@subquery);22 set@execcount=@execcount+123 end

这次做10次查询还是没有多大的差距,with语句用10个duration,子查询用了11个,有时候还会翻过来。于是把执行次数改成100,这次还是子查询使用的时间要少,截图如下

最终结论,子查询好比with语句效率高。

作者:http://www.cnblogs.com/tylerdonet/

本文版权归作者和博客园共有,欢迎转载,但未经作者同意必须保留此段声明,且在文章页面明显位置给出原文连接,如有问题,可以通过以下邮箱地址

sql语言和c语言比,SQL点滴10—使用with语句来写一个稍微复杂sql语句,附加和子查询的性能对比...相关推荐

  1. SQL点滴9—使用with语句来写一个稍微复杂sql语句

    今天偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章,自己添加了一些内容,做了简 单的总结,这个语句还是第一次见到,学习了.我从简单到复杂地写 ...

  2. 使用with语句来写一个稍微复杂sql语句(经典,转载)

    偶尔看到sql中也有with关键字,好歹也写了几年的sql语句,居然第一次接触,无知啊.看了一位博主的文章,自己添加了一些内容,做了简单的总结,这个语句还是第一次见到,学习了.我从简单到复杂地写,希望 ...

  3. SQL语言和T-SQL语言简介

    原文地址:https://www.2cto.com/database/201505/400750.html SQL语言简介 结构化查询语言(SQL)是一个非过程化的语言,它一次处理一个记录,对数据提供 ...

  4. 1.实现sql语言中DQL语言,实现简单查询、条件查询、排序查询等。

    1.实现sql语言中DQL语言,实现简单查询.条件查询.排序查询等. (1)检索grade表当中的所有信息. (2)检索grade表数学成绩大于100的所有人信息. <%@ page langu ...

  5. c语言 python-C语言、Java语言和python语言的区别在哪里

    原标题:C语言.Java语言和python语言的区别在哪里 我们经常听到C语言.Java语言和python语言,那么这三者的区别在哪里呢?随着科技的进步以及新技术的推进,编程语言的种类也是越来越多,随 ...

  6. php和java语言_JAVA语言和PHP语言的比较

    JAVA语言和PHP语言的比较 JAVA语言在服务器端开发的流行以及安卓客户端开发的流行,让他占据了大部分市场份额.在服务器端还有一个语言也较为流行,就是PHP.PHP语言由于简单易学,响应速度快,在 ...

  7. C语言和C++语言关系

    C语言和C++语言关系 C语言是在实践的过程中逐步完善起来的 C语言的目标是高效 C语言和C++并不是对立的竞争关系 C语言是在实践的过程中逐步完善起来的 没有深思熟虑的设计过程 使用时存在很多&qu ...

  8. C 语言和C++语言的 struct对比

    C 语言和C++语言的 struct对比 author: stonehat 1. C++语言将struct当成类来处理的,所以C++的struct可以包含C++类的所有东西,例如构造函数,析构函数,友 ...

  9. dart语言和java语言_Java不是文明语言吗?

    dart语言和java语言 几周前,我有机会学习iOS编程. 我的老板认为我更像是"计算机科学家",而不是开发人员,这意味着我可以将自己的知识应用于开发一两个iPad应用程序–我要 ...

最新文章

  1. 请说明在.net中常用的几种页面间传递参数的方法,并说出他们的优缺点。
  2. NSA释出逆向工程工具GHIDRA针对恶意软件逆向分析
  3. Garbage Collection Optimization for High-Throughput and Low-Latency Java Applications--转载
  4. 翻转字符串里面的单词(*****)
  5. oracle linux查看磁盘,fdisk命令_Linux fdisk命令使用详解:查看磁盘使用情况与磁盘分区...
  6. Linux Makefile
  7. android复习第二天------布局
  8. linux shell的组成,理解Linux中子shell的概念
  9. 多线程的那点儿事(之生产者-消费者)
  10. Android手机安全性测试手段
  11. 解决ant编译中出现“includeantruntime was not set”警告的问题
  12. xmlObj转为数组
  13. java中汉语转化成拼音的使用详解
  14. 转炉炼钢计算机仿真实训,转炉炼钢生产仿真实训(高职高专十二五规划教材)
  15. 职业规划(一)怎么写简历
  16. 计算机基础知识 图文,关于电脑基础知识学习【图文详解】
  17. 谷歌浏览器扩展程序XDM_这才是谷歌浏览器的正确打开方式,有效节省内存占用,流畅飞起...
  18. 第一次如何选择流量卡,长期套餐和短期套餐哪个好一点?
  19. Debian / Ubuntu下轻松切换GDM, LightDM , KDM
  20. 国信证券学习系列(5)

热门文章

  1. java11纳秒时间的局限性
  2. m软件接收机中同步技术以及LMS-RLS自适应均衡技术的matlab仿真
  3. 快速解决java中的容器
  4. Python爬虫实战+数据分析+数据可视化(猫眼电影)
  5. 我把华为小米年报放一起,发现华为才是真·手机公司,小米确实不靠卖手机赚钱...
  6. 集成灶好还是传统灶好,听内行人说完,才知道买错了
  7. “揭秘”低代码平台中的安全协同办公功能
  8. 眼科常用药物及其副作用
  9. 股票入门基础知识:可转债回售与强制赎回(上)
  10. 程序员常用英语词汇(034)