最近为了帮其他组赶项目,着实当了一把hive sql工具人,最大的收获还是系统的了解了case when、开窗函数的应用。为了便于以后回顾使用,特整理成文章进行记录分享。

一、case when

1.1 定义

hive官网( CASE Expression - PL/HQL Reference - HPL/SQL - Procedural SQL on Hadoop, NoSQL and RDBMS )一般不是叫case when,而是称为case表达式,其官方语法格式有两类,如下:

1) Simple CASE expression: 简单case表达式

CASE expr
  WHEN expr THEN expr
  [ELSE expr] 
END

2) Searched CASE expression: 搜索类case表达式

CASE 
  WHEN boolean_expr THEN expr
  [ELSE expr] 
END

注意:
1)如果when表达式未匹配,且else没有定义,则会返回null。
2)Case函数只返回第一个符合条件的值,剩下的when部分将会被自动忽略。
3)简单case表达式仅支持直接匹配,不支持判断式的选择,在搜索类Case表达式中,可以使用 BETWEEN、LIKE、IS NULL、IN、EXISTS 等进行条件判断。因此实际使用中搜索类表达式用的比较多(概念比较抽象,下面举个例子)

/** 简单case表达式,支持直接匹配 **/
select 
    name,
    (CASE sex WHEN 'male' THEN '男' ELSE '女' END ) as sex
    persons
/** 搜索类case表达式,支持判断式 **/
select 
    name,
    (CASE WHEN sex = 'male' THEN '男' ELSE '女' END ) as sex
    persons

1.2、使用场景

1)列值的简单修改替换
简单case表达式和搜索类case表达式都可以实现,如上面的性别替换

select 
    name,
    (CASE sex WHEN 'male' THEN '男' ELSE '女' END ) as sex
    persons

2)根据不同条件对数据进行不同的 普通处理 / 聚合处理
因为简单case表达式不支持条件判断,所以这种一般只能用搜索类case表达式,如对不同成绩段的学生打上优良差三种标签。

select 
    name,
    (case
        when grade > 90 then 'excellent' 
        when grade > 70 then 'good'
        else 'poor' end
    ) as grade_label
    persons

上面是普通处理,下面举个聚合处理的例子,比如统计男生女生的人数

select
    /** 统计男生数量,如果表中数据重复不能用该方式统计 */
    sum(case when sex = 'male' then 1 else 0 end) as boy_nums,
    /** 统计女生数量,如果表中数据重复则在case 前面加distinct字段进行去重 */
    /** count(distinct case when sex = 'female' then name else null end) as girl_nums */
    count(case when sex = 'female' then name else null end) as girl_nums
    persons

注意:
上面这个例子有几个点可以留意下,工作中较常用。
一是在某些情况下sum和count的相互转换;
二是聚合函数与case when的整合;
三是distinct字段在case when中的使用方式(不匹配返回null表示不纳入计算);

3) 分组数据 进行不同的 聚合处理
比如统计男生年龄的总和和女生分数的总和

select
    sum(case when sex = 'male' then age else 0 end) as boy_age_total,
    sum(case when sex = 'female' then grade else 0 end) as girl_grade_total,
    persons
group by
    sex

1.3 优势

目前感受比较明显的有两点,一是sql编辑更加灵活,二是提升性能,在一轮过滤条件下计算多种条件匹配下的数据。

二、连续区间查询

比如说统计年龄段[0-10),[10-20),[20-30)的连续区间人数,如下:

select
    //注意这里不要用between语法,因为between左右区间都是闭区间,与我们的左闭右开不符合
    count(distinct case when age >=0  and age<10 then id else null end) as stage1,
    count(distinct case when age >=10 and age<20 then id else null end) as stage2,
    count(distinct case when age >=20 and age<30 then id else null end) as stage3
    persons

可以看到,使用case when 可以很灵活的定义查询的空间,而且结构清晰。
但是该方式不够智能自动化,一般是有多少区间就要加多少个case when,自然而然的也就要有多少个区间字段。如果能直接查询区间值然后group by,比如mysql的internal和elt结合可以几乎做到区间的自动统计。但是在hive sql中我目前还未发现该使用方式,如果有哪位道友知道,欢迎留言指导,谢谢!

glide引用android glide android

//该死的拖延症,总是要学习做笔记,纸上得来终觉浅。一、简介、使用。1.1简介略,见 主页1.2基本使用Glide.with(imageView.getContext()) .load(url) .placeholder(defaultImage) .error(failImage) .diskCacheStrategy(DiskCacheStrategy.ALL) .into(imageView