码迷,mamicode.com
首页 > 数据库 > 详细

WITH AS ,case when then else end 在sql中的运用

时间:2015-04-16 14:33:25      阅读:913      评论:0      收藏:0      [点我收藏+]

标签:with as   case when then else end   

   WITH FOOTNOTE_LIST (CARRIER_CD, TARIFF_CD, FOOTNOTE_CD, CATEGORY_NO, SEQUENCE_NO)
     AS (SELECT DISTINCT X.CARRIER_CD,
          X.TARIFF_CD,
          X.FOOTNOTE_CD,
          X.CATEGORY_NO,
          X.SEQUENCE_NO
      FROM  ${parSchema}FTNREC2_CATCTRL X 
      INNER JOIN ${parSchema}FTNBATCH Y
      ON X.FTNT_BTCH_SG = Y.FTNT_BTCH_SG
      WHERE  X.FOOTNOTE_CD = :ftntCode
                AND X.CATEGORY_NO = :categoryNumber
       AND Y.FTNT_BTCH_SG IN ( :batchSGs ))
       
   SELECT A.CARRIER_CD,
       A.TARIFF_CD,
       A.FOOTNOTE_CD,
       A.CATEGORY_NO,
       A.SEQUENCE_NO,
       A.FTNREC2_SG,
       A.CREATE_TS,
       A.BATCH_CI,
       A.BATCH_NO,
       A.LOCALE_1_TYPE,
       A.LOCALE_1_CD,
       A.LOCALE_2_TYPE,
       A.LOCALE_2_CD,
       A.EDOT_ACTION_TG,
       A.POSTPONE_ACTION_TG,
       CASE WHEN B.BATCH_STATUS_TG IS NULL THEN ‘F‘ ELSE B.BATCH_STATUS_TG END AS BATCH_STATUS_TG,
       B.FTNT_BTCH_SG,
       C.SEGMENT_ORDER_NO,
       C.FTNCAT_SG,
       C.RELATIONAL_IND,
       C.INBND_OUTBND_TG,
       C.DIRECTIONAL_TG
   FROM   FOOTNOTE_LIST T
     INNER JOIN ${parSchema}FTNREC2_CATCTRL A
       ON T.CARRIER_CD = A.CARRIER_CD
     AND T.TARIFF_CD = A.TARIFF_CD
     AND T.FOOTNOTE_CD = A.FOOTNOTE_CD
     AND T.CATEGORY_NO = A.CATEGORY_NO
     AND T.SEQUENCE_NO = A.SEQUENCE_NO
     LEFT OUTER JOIN ${parSchema}FTNBATCH B
      ON A.FTNT_BTCH_SG = B.FTNT_BTCH_SG
     LEFT OUTER JOIN ${parSchema}FTNSTR_CAT C
      ON A.FTNREC2_SG = C.FTNREC2_SG
     ORDER  BY A.CARRIER_CD,
      A.TARIFF_CD,
      A.FOOTNOTE_CD,
      A.CATEGORY_NO,
      A.SEQUENCE_NO,
      A.FTNREC2_SG,
      C.SEGMENT_ORDER_NO,
      A.CREATE_TS

================================

使用WITH AS提高性能简化嵌套SQL

一.WITH AS的含义

    WITH AS短语,也叫做子查询部分(subquery factoring),可以让你做很多事情,定义一个SQL片断,该SQL片断会
被整个SQL语句所用到。有的时候,是为了让SQL语句的可读性更高些,也有可能是在UNION ALL的不同部分,作为提供数
据的部分。
特别对于UNION ALL比较有用。因为UNION ALL的每个部分可能相同,但是如果每个部分都去执行一遍的话,则成本太高,
所以可以使用WITH AS短语,则只要执行一遍即可。如果WITH AS短语所定义的表名被调用两次以上,则优化器会自动将
WITH AS短语所获取的数据放入一个TEMP表里,如果只是被调用一次,则不会。而提示materialize则是强制将WITH AS
短语里的数据放入一个全局临时表里。很多查询通过这种方法都可以提高速度。

二.使用方法

先看下面一个嵌套的查询语句:

select * from person.StateProvince where CountryRegionCode in 
        (
select CountryRegionCode from person.CountryRegion where Name like C%)

上面的查询语句使用了一个子查询。虽然这条SQL语句并不复杂,但如果嵌套的层次过多,会使SQL语句非常难以阅
读和维护。因此,也可以使用表变量的方式来解决这个问题。

SQL语句如下:

declare @t table(CountryRegionCode nvarchar(3)) 
insert into @t(CountryRegionCode)  (select CountryRegionCode from person.CountryRegion where Name like C%)

select * from person.StateProvince where CountryRegionCode
                   
in (select * from @t)

 


    虽然上面的SQL语句要比第一种方式更复杂,但却将子查询放在了表变量@t中,这样做将使SQL语句更容易维护,但又
会带来另一个问题,就是性能的损失。由于表变量实际上使用了临时表,从而增加了额外的I/O开销,因此,表变量的方式
并不太适合数据量大且频繁查询的情况。为此,在SQL Server 2005中提供了另外一种解决方案,这就是公用表表达式(CTE),使用CTE,可以增加SQL语句的可维护性,同时,CTE要比表变量的效率高得多。

下面是CTE的语法:

[ WITH <common_table_expression> [ ,n ] ]
<common_table_expression>::=
        expression_name [ ( column_name [ ,n ] ) ]
    AS
        ( CTE_query_definition )


现在使用CTE来解决上面的问题,SQL语句如下:

技术分享

with 
cr
as
(
   
select CountryRegionCode from person.CountryRegion where Name like C%
)

select * from person.StateProvince where CountryRegionCode in (select * from cr)

技术分享

 

    其中cr是一个公用表表达式,该表达式在使用上与表变量类似,只是SQL Server 2005在处理公用表表达式的方式上有
所不同。

在使用CTE时应注意如下几点:

1. CTE后面必须直接跟使用CTE的SQL语句(如select、insert、update等),否则,CTE将失效。如下面的SQL语句将无法正
常使用CTE:

技术分享

with 
cr
as
(
   
select CountryRegionCode from person.CountryRegion where Name like C%
)
select * from person.CountryRegion  -- 应将这条SQL语句去掉
--
使用CTE的SQL语句应紧跟在相关的CTE后面--
select * from person.StateProvince where CountryRegionCode in (select * from cr)

技术分享

 


2. CTE后面也可以跟其他的CTE,但只能使用一个with,多个CTE中间用逗号(,)分隔,如下面的SQL语句所示:

技术分享

with 
cte1
as
(
   
select * from table1 where name like abc%
),
cte2
as
(
   
select * from table2 where id > 20
),
cte3
as
(
   
select * from table3 where price < 100
)
select a.* from cte1 a, cte2 b, cte3 c where a.id = b.id and a.id = c.id

技术分享

 


3. 如果CTE的表达式名称与某个数据表或视图重名,则紧跟在该CTE后面的SQL语句使用的仍然是CTE,当然,后面的SQL语句
使用的就是数据表或视图了,如下面的SQL语句所示:

技术分享

--  table1是一个实际存在的表
with
table1
as
(
   
select * from persons where age < 30
)
select * from table1  --  使用了名为table1的公共表表达式
select * from table1  --  使用了名为table1的数据表

技术分享

 


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

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

(1)COMPUTE 或COMPUTE BY

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

(3)INTO

(4)带有查询提示的OPTION 子句

(5)FOR XML

(6)FOR BROWSE


6. 如果将CTE 用在属于批处理的一部分的语句中,那么在它之前的语句必须以分号结尾,如下面的SQL所示:

技术分享

declare @s nvarchar(3) 
set @s = C%
;  
-- 必须加分号
with
t_tree
as
(
   
select CountryRegionCode from person.CountryRegion where Name like @s
)
select * from person.StateProvince where CountryRegionCode in (select * from t_tree)

====================================================================

CASE命令有两种语句格式。
语法形式1:CASE expression
           WHEN expression_11 THEN expression_12
            …
           WHEN expression_n1 THEN expression_n2
           [ELSE expression_m]
           END
该语句的执行过程是:将CASE后面表达式的值与各WHEN子句中的表达式的值进行比较,如果两者相等,则返回THEN后的表达式的值,然后跳出CASE语句,否则返回ELSE子句中的表达式的值。ELSE子句是可选项。当CASE语句中不包含ELSE子句时,如果所有比较失败时,CASE语句将返回NULL。
【例】从数据表stud_info中,选取stud_id、grade,如果grade为“男”则输出“M”,如果为“女”输出“F”。
SELECT stud_id, sex=CASE gender
                     WHEN ’男’ THEN ’M’
                     WHEN ’女’ THEN ’F’
                   END
FROM stud_info
语法形式2:CASE WHEN condition_expression_1 THEN expression_1
             …
            WHEN condition_expression_n THEN expression_n
            [ELSE expression_m]
          END
该语句的执行过程是:首先测试WHEN后的条件表达式的值,如果其值为真,则返回THEN后面的表达式的值,否则测试下一个WHEN子句中的表达式的值,如果所有WHEN子句后的表达式的值都为假,则返回ELSE后的表达式的值,如果在CASE语句中没有ELSE子句,则CASE表达式返回NULL。
注意:CASE命令可以嵌套到SQL语句中。

【例】从stud_grade表中查询所有同学考试成绩情况,凡成绩为空者输出“未考”、小于60分输出“不及格”、60分至70分输出“及格”、70分至90分输出“良好”、大于或等于90分时输出“优秀”。
SELECT stud_id,name,score=CASE WHEN grade IS NULL THEN ’未考’
                             WHEN grade<60 THEN ’不及格’
                             WHEN grade>=60 AND grade<70 THEN ’及格’
                             WHEN grade>=70 AND grade<90 THEN ’良好’
                             WHEN grade>=90 THEN ’优秀’
                        END
FROM stud_grade

 

Case具有两种格式。简单Case函数和Case搜索函数。 
--简单Case函数 
CASE [object Object]sex 
WHEN ‘1‘ THEN ‘男‘ 
WHEN ‘2‘ THEN ‘女‘ 
ELSE ‘其他‘ END 
--Case搜索函数 
CASE WHEN sex = ‘1‘ THEN ‘男‘ 
WHEN sex = ‘2‘ THEN ‘女‘ 
ELSE ‘其他‘ END 

这两种方式,可以实现相同的功能。简单Case函数的写法相对比较简洁,但是和Case搜索函数相比,功能方面会有些限制,比如写判断式。 
还有一个需要注意的问题,Case函数只返回第一个符合条件的值,剩下的Case部分将会被自动忽略。
两者中可以根据不同的需求来选择

 

其它网友的实例:

 Id     name        dept
1        aa          dept1
2        bb          dept1
3        cc           dept2

SELECT SUM(CASE decp WHEN ‘decp1‘ THEN 1 ELSE 0 end ) AS decp1,
sum(case decp when ‘decp2‘then 1 else 0 end)as decp2
FROM teacher

生成:

dept1     dept2

2             1

 

 

 

有一张表,里面有3个字段:语文,数学,英语。其中有3条记录分别表示语文70分,数学80分,英语58分,请用一条sql语句查询出这三条记录并按以下条件显示出来(并写出您的思路):
大于或等于80表示优秀,大于或等于60表示及格,小于60分表示不及格。
显示格式:
语文 数学 英语
及格 优秀 不及格
------------------------------------------
select
(case when 语文>=80 then ‘优秀‘
when 语文>=60 then ‘及格‘
else ‘不及格‘) as 语文,
(case when 数学>=80 then ‘优秀‘
when 数学>=60 then ‘及格‘
else ‘不及格‘) as 数学,
(case when 英语>=80 then ‘优秀‘
when 英语>=60 then ‘及格‘
else ‘不及格‘) as 英语,
from table

  CASE 可能是 SQL 中被误用最多的关键字之一。虽然你可能以前用过这个关键字来创建字段,但是它还具有更多用法。例如,你可以在 WHERE 子句中使用 CASE。

  首先让我们看一下 CASE 的语法。在一般的 SELECT 中,其语法如下:

  SELECT <myColumnSpec> =
      CASE
      WHEN <A> THEN <somethingA>
      WHEN <B> THEN <somethingB>
      ELSE <somethingE>
      END

  在上面的代码中需要用具体的参数代替尖括号中的内容。下面是一个简单的例子:

  USE pubs
      GO
      SELECT
      Title,
      ‘Price Range‘ =
      CASE
      WHEN price IS NULL THEN ‘Unpriced‘
      WHEN price < 10 THEN ‘Bargain‘
      WHEN price BETWEEN 10 and 20 THEN ‘Average‘
      ELSE ‘Gift to impress relatives‘
      END
      FROM titles
      ORDER BY price
      GO

  这是 CASE 的典型用法,但是使用 CASE 其实可以做更多的事情。比方说下面的 GROUP BY 子句中的 CASE:

  SELECT ‘Number of Titles‘, Count(*)
      FROM titles
      GROUP BY
      CASE
      WHEN price IS NULL THEN ‘Unpriced‘
      WHEN price < 10 THEN ‘Bargain‘
      WHEN price BETWEEN 10 and 20 THEN ‘Average‘
      ELSE ‘Gift to impress relatives‘
      END
      GO

  你甚至还可以组合这些选项,添加一个 ORDER BY 子句,如下所示:

  USE pubs
      GO
      SELECT
      CASE
      WHEN price IS NULL THEN ‘Unpriced‘
      WHEN price < 10 THEN ‘Bargain‘
      WHEN price BETWEEN 10 and 20 THEN ‘Average‘
      ELSE ‘Gift to impress relatives‘
      END AS Range,
      Title
      FROM titles
      GROUP BY
      CASE
      WHEN price IS NULL THEN ‘Unpriced‘
      WHEN price < 10 THEN ‘Bargain‘
      WHEN price BETWEEN 10 and 20 THEN ‘Average‘
      ELSE ‘Gift to impress relatives‘
      END,
      Title
      ORDER BY
      CASE
      WHEN price IS NULL THEN ‘Unpriced‘
      WHEN price < 10 THEN ‘Bargain‘
      WHEN price BETWEEN 10 and 20 THEN ‘Average‘
      ELSE ‘Gift to impress relatives‘
      END,
      Title
      GO

  注意,为了在 GROUP BY 块中使用 CASE,查询语句需要在 GROUP BY 块中重复 SELECT 块中的 CASE 块。

WITH AS ,case when then else end 在sql中的运用

标签:with as   case when then else end   

原文地址:http://5618698.blog.51cto.com/5608698/1633301

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!