由于程序员所在公司环境不太一样,所以造成程序员在IT技能方面有比较大的差别。例如有些公司,程序员大多只关心业务逻辑处理或者是页面UI,当然我指的是web应用程序相关的程序员。因为有可能所有的底层数据都由其它同事给你提供,这样就造成一旦需要自己写数据库脚本查询时,那些难以想像的,丑陋的SQL就出来了,不过如果我们稍加注意,就会知道SQL 2005的CTE在很大程序上能解决这种境况,这就看程序员的自身提高意识了。

一提到SQL的CTE,大家很有可能第一反应就是它强大的递归查询,但我这里并不想讲这方面知识。

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

CTE分类:1:递归CTE;2:非递归CTE。
 
      我今天总结的就是第二种,上面提到过CTE的合理利用可以避免出现丑陋的SQL,先贴一条嵌套查询的SQL:我想大家看到这样的SQL,短时间内很难搞清楚它真正的意图。

代码

SELECT  r.room_type AS room_type,
        a.*
FROM    ( SELECT    f.id,
                    end_date,start_date,
                    ( f.room_num - ISNULL(( SELECT  SUM(a.free_room_used)
                                            FROM    C a
                                            WHERE   a.free_room_id = f.id
                                            GROUP BY a.free_room_id
                                          ), 0) ) AS free_num
          FROM      A f
          WHERE     ( f.deleted <> 1
                      OR f.deleted IS NULL
                    )
                    AND '2010-3-16' BETWEEN f.start_date AND f.end_date
        ) a
        INNER JOIN B r ON r.room_type_id = a.room_type_id
                                      AND ( r.notes = 'all'
                                            OR r.notes = '40101035'
                                          )
WHERE   a.free_num > 0
ORDER BY a.end_date,
        a.start_date

我们再来看看CTE改善后的写法:可以看出没有了嵌套,分别用两个CTE来代替子查询。

代码

BEGIN
       WITH    freeroom
              AS ( SELECT   SUM(a.free_room_used) AS used,
                            free_room_id
                   FROM     C a
                            INNER JOIN B f ON a.free_room_id = f.id
                   GROUP BY a.free_room_id
                 ) ,
            freehotel
              AS ( SELECT   r.room_type AS room_type,
                            f.id,
                            start_date,end_date,
                            ( f.room_num - ISNULL(fr.used, 0) ) AS free_num
                   FROM     A f
                            LEFT JOIN freeroom fr ON f.id = fr.free_room_id
                            INNER JOIN B r ON r.room_type_id = f.room_type_id
                                                          AND ( r.notes = 'all'
                                                                OR r.notes = '40101035'
                                                              )
                   WHERE    ( f.deleted <> 1
                              OR f.deleted IS NULL
                            )

AND '2010-3-16' BETWEEN f.start_date AND f.end_date
                 )
        SELECT  *
        FROM    freehotel
        WHERE   free_num > 0
        ORDER BY end_date,
        start_date

END

第一:尽量避免在查询字段,例如上例中取free_num,直接嵌套查询,这种写法看着就让人不舒服。
               改进:把这个子查询用一个CET表达式表示出来,见上面的freeroom。

第二:上述示例中,由于free_num这个字段并不是表中实际存在的字段,是通过计算等到的,所以要想以它做为where条件,不得不再嵌套一次。

改进:我们把上面的子表也用CTE表示出来,见上面的freehotel。

第三:直接查询freehotel,然后加上查询条件以及排序语句即可。

小结:通过以上三步,就把上面嵌套了两层的查询给分清楚了,化整为零后再分析,思路就清晰多了。

注意事项:这是针对的都是非递归CTE

1:CTE 之后必须跟随引用部分或全部 CTE 列的单条 SELECT、INSERT、UPDATE 或 DELETE 语句。也可以在 CREATE VIEW 语句中将 CTE 指定为视图中 SELECT 定义语句的一部分,否则CTE会失效。

2:不允许在一个 CTE 中指定多个 WITH 子句。

3:CTE 可以引用自身,也可以引用在同一 WITH 子句中预先定义的 CTE。不允许前向引用。

像上面例子中同一with下面,事先定义了freeroom,后面的freehotel使用了前面的freeroom。

4:不能在 CTE_query_definition 中使用以下子句:

COMPUTE 或 COMPUTE BY

ORDER BY(除非指定了 TOP 子句)
         INTO

带有查询提示的 OPTION 子句
         FOR XML
         FOR BROWSE

5:如果将CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾。

这种说法的另外一种做法就是,让整个cte定义以及最后的操作,都用begin,end begin块包含起来,这样可以避免和其它语句形成一个批处理。

CTE与表变量的关系:非递归的CTE在很大程序上能代替表变量,当然唯一的不同点在于,表变量能够在整个查询过程中有效,而CTE后面需要马上进行调用,但好处在于节约开销,因为表变量是会额外增加系统I/O开销。而且CTE并不需要像表变量一样,在使用前需要定义好表结构,并且具有维护性高的优点。

作者:姜敏
出处:http://www.cnblogs.com/aspnet2008/

 

转载于:https://www.cnblogs.com/ASPNET2008/archive/2010/03/17/1688533.html

SQL CTE能帮助我做什么相关推荐

  1. sql cte递归_准备好,开始吧– SQL Server如何处理递归CTE

    sql cte递归 First of all, a quick recap on what a recursive query is. 首先,快速回顾一下递归查询是什么. Recursive quer ...

  2. Sql — CTE公用表表达式和With用法总结

    CTE(Common Table Expression) 公用表表达式,它是在单个语句的执行范围内定义的临时结果集,只在查询期间有效.它可以自引用,也可在同一查询中多次引用,实现了代码段的重复利用. ...

  3. SQL CTE学习总结

    一句SQL完成动态分级查询 http://www.cnblogs.com/powertoolsteam/p/sqlite.html 在最近的活字格项目中使用ActiveReports报表设计器设计一个 ...

  4. oracle spa sta 使用,Oracle的SQL Tuning Advisor(STA) 到底做了什么?

    5.使用STA优化awr中SQL的脚本 robin@SZDB:~/dba_scripts/custom/sql> more tune_awr_sql.sql SET ECHO OFF TERMO ...

  5. sql datetime比较大小_SQL做题小技巧

    数据分析必学必会当属SQL取数,毕竟要分析首先需要有数嘛. sql的语法教程往上一搜就有很多,本文主要将介绍几个sql小技巧,灵活用上技能做对大部分的笔试题. 由于很多笔试是在牛客网上完成的,所以本文 ...

  6. 在sql当中为了让数据做缓存做with as的操作

    今天看别人的代码,突然发现之前理解的sql的with as的用法有新的理解. 之前理解的with as只是想着做单表的union all 操作时才使用,今天发现在可以使用逗号做分割,做缓存不同的表数据 ...

  7. php sql语句过滤,php如何做sql过滤

    php如何做sql过滤 SQL注入攻击指的是通过构建特殊的输入作为参数传入Web应用程序,而这些输入大都是SQL语法里的一些组合,通过执行SQL语句进而执行攻击者所要的操作,其主要原因是程序没有细致地 ...

  8. oracle关联视图查询满_对于复杂的SQL, Oracle是怎么做的?

    很多人经常说,同样的SQL在Oracle中的查询性能要比在MySQL中好很多,大家有没有深究过其中的原因呢?除了MySQL 8.0之前不支持hash-join以外,还有其他原因吗?其实很多时候,出现这 ...

  9. 统计出库数,sql查询数据,sqldf做透视表,循坏处理数据

    #设置工作路径 D:\资料\天富盈\天富盈\erp\erp录入 setwd("D:\\资料\\程序文档")#设置文件名 path="C:\\Users\\Jarvis\\ ...

最新文章

  1. springmvc 配置 fastjson解析器
  2. android 反编译报错,android反编译
  3. 连接远程电脑中的虚拟机---端口映射
  4. iphone最新款手机_苹果罕见“跌停”!遭遇6年来最惨淡一夜,2019年全球股市第一颗雷引爆...
  5. 通过OAuth 2.0和Okta使用安全的服务器到服务器通信构建Spring Boot应用
  6. LeetCode(90):子集 II
  7. bzoj 4660 Crazy Rabbit——LIS解决“相交”限制的思想
  8. redis连接数据库进行操作
  9. servlet处理多个请求 笔记
  10. 台达PLC,触摸屏程序工程案例 含电气图 台达与伺服变频通讯实例
  11. JS字符串转换为JSON的四种方法
  12. UTONMOS:中国区块链专利申请数量占全球总量的84%
  13. 台式计算机亮度怎么调节快捷键,详解电脑调亮度快捷键如何调整屏幕亮度呢?...
  14. 通信室计算机室采购配置co2灭火器,2019一级消防案例分析考点:民用类建筑消防设施的配置...
  15. 中国十大悍匪排行榜,屌爆了!!!!
  16. 《男孩别哭》海龟先生
  17. Xshell 基础命令及其打包静态库和动态库命令
  18. MacBook 安装 win10 系统的方法
  19. win10安装mangodb 5.x无法启动服务, 提示:错误1053:服务没有及时响应启动或控制请求.
  20. ChromeOptions

热门文章

  1. 关于考研的反思与总结
  2. Python传递参数的5种方式
  3. 牛客网剑指offer-02替换空格
  4. 试试用pyqt做一个上位机软件,但愿不会烂尾(七):费了九牛二虎之力的进度条显示
  5. 计算机操作员(高级),计算机操作员(高级)
  6. MATLAB 函数或变量 ‘XXX’ 无法识别
  7. 豪掷重金收购美国“b站”Crunchyroll,索尼流媒体野心有多大?
  8. 如何利用多层循环找出对称的3位数数字?
  9. MATLAB 绘制三维坐标系下的矩形框
  10. SEH转化为C++异常二