• CASE表达式


    一、简介   

      官方定义CASE是一种表达式,它基于某种格式,按照格式去编写表达式,其中表达式的逻辑是:指定特定的值与条件列表去匹配,返回对应的值。

      CASE表达式类似我们编程语言中的 if else 和 switch 的逻辑,那么久代表我们可以拿一些值做判断,做出与之对应的处理。

      CASE表达式的用途很广,在开发中使用率也很高,所以个人觉得有必要把这个基础的知识点吃透。CASE表达式用的最多的就是SELECT查询语句中,但也不局限于此。

      实际上CASE表达式可以用于允许使用有效表达式的任意语句或子句中。例如SELECT、UPDATE、DELETE、和SET等语句以及select_list、IN、WHERE、ORDER BY、HAVING等子句中使用CASE。

       CASE表达式有两种格式:

        1.简单格式:用一个值或者属性或者表达式,去与一个条件列表做等值判断,匹配到相等的,则返回条件列表对应的结果。

        2.搜索格式:像极了编程语言中if else 和 switch,在一个或多个布尔表达式中匹配一个结果为true的,然后返回对应的处理结果。

    二、语法初探

    --简单格式 CASE表达式
    CASE input_expression   
         WHEN when_expression THEN result_expression [ ...n ]   
         [ ELSE else_result_expression ]   
    END   
    
    --搜索模式
    CASE  
         WHEN Boolean_expression THEN result_expression [ ...n ]   
         [ ELSE else_result_expression ]   
    END 

     input_expression(简单格式):

    指定一个有效的表达式(可以是常量、变量、列属性),只要表达式返回的是单个数据值。

    when_expression(简单格式):

    在简单格式中,此处填写的内容是用于和input_expression表达式进行等值比较的。when_expression的内容可以是任何有效的表达式,可以指定多个。

    input_expression和when_expression的注意事项(简单格式):

    在简单模式中,input_expression和when_expression表达式计算的结果值,要求数据类型必须相同,如果不满足则两个结果值必须满足隐式转换的条件。如果两个条件都不满足,则会提示“数据类型转换失败”。

    result_expression:

    CASE表达式匹配后返回的结果,结果可以指定任何有效的表达式。

    简单格式:当 input_expression = when_expression的计算结果相等时,将其返回。

    搜索格式:当Boolean_expression表达式计算结果为true时,将其返回。

     else_result_expression:

     一个可选的部分,可以指定有效的表达式,逻辑和编程语言中的ELSE是一个逻辑。当指定值和比较值列表没有一个匹配为true时,将其作为结果返回。

    如果没有指定else_result_expression表达式并且匹配结果都不为true时,那么最终返回NULL。

    Boolean_expression(搜索格式):

    使用搜索格式时的写法,可以指定一个有效的布尔表达式,并且可以指定多个。例如,“age>18”、“score between 60 and 100”等。

    三、关于CASE表达式返回值的数据类型

      在编写CASE表达式的时候,往往我们要编写多个对比的条件列表,那么就意味着对应也有多个返回结果。

      当CASE表达式匹配某个条件成功时,会返回相应的处理结果,那么在这个返回结果的数据类型上有一个细节。

      这个细节的定论是:当CASE表达式有多个可能返回的结果列表时,匹配成功的这个结果的数据类型,会从结果列表中(包括else部分),参照SQL Server数据类型优先级的规则,选择一个优先级最高的作为返回结果的数据类型。正常的思维逻辑是返回的结果值和数据类型是对应的。例如,1代表int类型、'a'代表字符类型。但是实际结果往往让我们意外,示例图如下:

      (如果CASE表达式匹配返的结果的数据类型)和(在所有结果中根据数据类型优先级规则确定了的数据类型)不相同,并且也不符合隐式转换,那么执行的时候就会出现错误。

       示例图:

       

        如果 返回结果'二'写成'2',那么就符合隐式转换,查询可以成功执行。

        

     四、CASE表达式的运用示例

    A.在SELECT语句中使用简单格式

    简单格式的工作逻辑:根据CASE关键字后指定的表达式,去和一个或多个when子句中的表达式进行比较,这种比较是等值比较判断两者是否相等。

    业务场景:某旅游网站想查询出其下合作的酒店信息,酒店信息来自主要酒店表,用户想要知道酒店的对应星级名称,因为星级就那么固定几个(1-5),所以在建的时候没有必要建立主外键关联表,

         对应的数据列存储的1-5的数字。显然直接查询显示不太友好和明确,对于这种特定标识特定的语义化的情况,就是使用CASE表达式简单格式的最佳场景。

    示例代码:    

    select hotelsName, address,phone,
    case grade 
        when 1 then '一星级'
        when 2 then '二星级'
        when 3 then '三星级'
        when 4 then '四星级'
        when 5 then '五星级'
        else '未知' end as grade
    from Hotels

    B.在SELECT语句中使用搜索格式

    搜索格式的工作逻辑:指定一个或多个when子句,并在其指定布尔表达式,和对应的返回结果。

    搜索格式和简单格式对比:书写结构上和简单格式相似,搜索格式在CASE关键字后没有指定表达式,而是在when子句中指定布尔表达式。

                搜索格式显然在逻辑上更灵活,而且搜索格式显然可以兼容简单格式的判断逻辑,简单格式则只局限于等值判断。     

    业务场景:根据数值范围,作出逻辑的定义。某婚恋网站,想查询男性用户时根据年龄,然后根据特定逻辑的范围,对用户打上年龄化的标签。

    示例代码:

    select  case
        when Age>18 and Age <30 then '小鲜肉'
        when Age>30 and Age <45 then '熟男' 
        when Age>45  and Age<50 then '大叔'  end ageFlag
      from  Student
      where Gender=''

    C.在ORDER BY子句中使用CASE

    业务场景:老师想查询学生的成绩信息。对于及格的(passFlag=1)学生的成绩分数想看从高到底查看,以便更好的培养尖子生。对于不及格(passFlag=0)的学生的成绩分数想从底到高查看,以便不同情况对差生进行补习。

    示例代码:

    select b.passFlag,a.StudentId,a.StudentName,(b.CSharp+b.SQLServerDB) as score
    from Student  a
    inner join ScoreList  b on a.StudentId=b.StudentId
    order by  case passFlag when 0 then (b.CSharp+b.SQLServerDB)  end asc,
              case passFlag when 1 then (b.CSharp+b.SQLServerDB) end desc

    D.CASE表达式实现数据行专列

    在这里使用CASE表达式实现数据的行专列,并不是唯一可行的方法,而是通过此示例更好的融汇贯通CASE表达式的运用。对于行转列的这种特定的操作,SQL Server提供了PIVOT的方案来解决。

     CASE表达式实现行转列的方式依赖于的表结关联系:

    此关联中存在一个多对多的中间表,每行行会显示课程对应考的分数。观察这种关系结构和CASE表达式的特性,运用起来实现行转为列。在个示例图中,即课程转为列,列值显示分数。

    实现代码:

    select a.name ,
    MAX(case c.cid  when 1 then b.score end) as '语文',
    MAX(case c.cid when 2 then b.score end) as '数学',
    MAX(case c.cid when 3 then b.score end ) as '体育'
    from StudentInfo a
    inner join StuCourseGrade b on a.stuId=b.stuId
    inner join Curriculum c on b.cid=c.cid
    group by a.name 

    我们分析一下查询逻辑如何进行的处理:

          

  • 相关阅读:
    sed命令用法详解
    Linux date命令的用法
    安装oracle客户端连接工具
    nginx安装
    orabbix监控oracle数据库
    Oracle数据库修改用户密码
    oracle数据库重启操作
    centos6.5安装oracle11.2.0.1.0数据库
    教你几招解决电脑假死现象
    (java实现)杭电oj 2097 Sky数
  • 原文地址:https://www.cnblogs.com/green-jcx/p/case.html
Copyright © 2020-2023  润新知