CASE表达式分为简单表达式和搜索表达式。搜索表达式可以涵盖简单表达式的所有功能。我还建议只编写搜索表达式而不是简单的表达式。简单表达式:SELECTCASEcityWHEN'北京'THEN1WHEN'天津'THEN2ELSE0ENDASabcFROMtest搜索表达式:SELECTCASEWHENcity='北京'THEN1WHENcity='天津'THEN2ELSE0ENDASabcFROMtest可以清楚地看到,简单表达式只是搜索表达式a=b的特例,因为不能写符号,只要把条件改成a>b就不行了,但是搜索表达式不行只能轻松胜任,但连聚合函数都可以写。CASE表达式中的聚合函数为什么聚合函数可以写在CASE表达式中?因为表达式本身支持聚合函数,比如下面的语法,我们不会感到奇怪:SELECTsum(pv),avg(uv)fromtestSQL本身支持多种不同的聚合方式同时计算,所以使用在CASE表达式中,也是很自然的:SELECTCASEWHENcount(city)=100THEN1WHENsum(dau)>200THEN2ELSE0ENDASabcFROMtest只要SQL表达式中有聚合函数,整个表达式就是聚合。此时访问非聚合变量没有意义。因此,在上面的例子中,即使在CASE表达式中使用了聚合,实际上也只是聚合了一次,根据条件进行判断。这个特性可以解决很多实际问题,比如在SQL结构中输出一些复杂的聚合判断条件的结果,那么很可能会这样写:SELECTCASEWHEN聚合函数(字段)满足什么条件THENxxx。..可能有NELSENULLENDASabcFROMtest这也可以看做是一个行到列的过程,即通过CASE表达式将行聚合的结果一一组成新的列。聚合和非聚合不能混用。我们希望通过CASE表达式找出那些pv大于平均值的行。下面的假设是错误的:SELECTCASEWHENpv>avg(pv)THEN'yes'ELSE'no'ENDASabcFROMtest的原因是只要SQL中有聚合表达式,整个SQL就聚合了,所以返回的结果只有一个,我们希望查询结果不聚合,但是判断条件使用的是聚合结果,所以必须使用子查询。为什么子查询可以解决问题?因为子查询的聚合发生在子查询中,不会影响当前的父查询,如果你理解了这一点,你就会知道为什么下面的写法是正确的:SELECTCASEWHENpv>(SELECTavg(pv)fromtest)THEN'yes'ELSE'no'ENDASabcFROM测试的例子也说明了在CASE表达式中可以使用子查询。因为子查询是先计算的,所以查询结果可以在任何地方使用,CASE表达式也不例外。WHERE中的CASEWHERE后面还可以跟CASE表达式,用来做一些需要特殊枚举处理的筛选。比如下面这个例子:SELECT*FROMdemoWHERECASEWHENcity='北京'THENtrueELSEID>5END本来我们想查询ID大于5的数据,但是我想对北京这个城市进行特殊处理,所以我们可以在判断条件下执行CASE分支判断。该场景相当于在BI工具中创建了一个CASE表达式字段,拖入过滤条件即可生效。GROUPBY中的CASE是意想不到的,可以在GROUPBY中写CASE表达式:SELECTisPower,sum(gdp)FROMtestGROUPBYCASEWHENisPower=1THENcity,areaELSEcityEND上面的例子说明在计算GDP的时候,对于非常发达的城市,按照各区的粒度查看聚合结果,也就是看更细的粒度。对于欠发达地区,gdp本身并不高,可以直接按照城市的粒度查看聚合结果。通过这种方式,数据根据不同的条件进行分组和聚合。由于返回行的结果是混合在一起的,如本例,可以根据isPower字段是否为1,判断是否按照城市和地区进行聚合。如果没有其他更突出的标识,可能会导致无法区分不同行的聚合粒度,请谨慎使用。ORDERBY中的CASE也是一样,ORDERBY使用CASE表达式,排序结果会按照CASE分类进行分组,每组按照自己的规则排序,例如:SELECT*FROMtestORDERBYCASEWHENisPower=1THENgdpELSEpeopleEND上面的例子,发达地区按gdp排序,否则按人口排序。总结CASE表达式总结起来有以下特点:支持simple和search两种写法,推荐使用search写法。支持聚合和子查询,需要注意不同情况的特点。它几乎可以写在SQL查询的任何地方,只要是可以写字段的地方,基本上都可以用CASE表达式代替。除了SELECT外,CASE表达式也广泛用于INSERT和UPDATE。UPDATE的妙用在于不需要将SQL拆成多块,不用担心数据变化后对判断条件的二次影响。讨论地址为:Jingdu《SQL CASE 表达式》·Issue#404·ascoders/weekly想参与讨论的请点这里,每周都有新话题,周末或周一发布。前端精读——帮你过滤靠谱的内容。关注前端精读微信公众号
