大数据之Hive函数及案例

7 函数

7.1 系统内置函数

#查看系统自带的函数
hive (default)> show functions;
#显示自带的函数的用法
hive (default)> desc function upper;
#详细显示自带的函数的用法
hive (default)> desc function extended upper;

7.1.1 常用函数

  • current_database():查询当前数据库。
  • nvl(expr1,expr2):判断expr1是否为null,如果为null用expr2替代,与mysql中ifnull用法相同。
  • case when:与mysql中用法相同。
  • if(expr,val1,val2):表达式为true时值为val1,为false时值为val2。
  • concat(str1,str2,...):拼接字符串,字符串中如果有NULL,则返回NULL。
  • concat_ws(separator, [string | array(string)]+):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL,分隔符将被加到被连接的字符串之间。
  • collect_set(col):仅支持基本数据类型,将某字段的值进行去重汇总,产生一个set集合。
  • collect_list(col): 将此列的多行记录合并为一个list集合,不去重。
  • explode:将一个array的元素分割成多行,或将一个map的元素分割成2列多行。
  • LATERAL VIEW:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合,用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias

7.1.2 常用日期函数

hive默认解析的日期必须是: 2019-11-24 08:09:10

  • unix_timestamp:返回当前或指定时间的时间戳
  • from_unixtime:将时间戳转为日期格式
  • current_date:当前日期
  • current_timestamp:当前的日期加时间
  • to_date:抽取日期部分
  • year:获取年
  • month:获取月
  • day:获取日
  • hour:获取时
  • minute:获取分
  • second:获取秒
  • weekofyear:当前时间是一年中的第几周
  • dayofmonth:当前时间是一个月中的第几天
  • months_between: 两个日期间的月份,前-后
  • add_months:日期加减月
  • datediff:两个日期相差的天数,前-后
  • date_add:日期加天数
  • date_sub:日期减天数
  • last_day:日期的当月的最后一天
  • date_format:格式化日期 date_format( 2019-11-24 08:09:10,‘yyyy-MM’) mn

7.1.3 常用取整函数

  • round:四舍五入
  • ceil:向上取整
  • floor:向下取整

7.1.4 常用字符串操作函数

  • upper:转大写
  • lower:转小写
  • length:长度
  • trim:前后去空格
  • lpad:向左补齐,到指定长度,如果str的长度大于len,则返回值将缩短为len个左边字符。如果填充字符串为空字符,则返回值为null
  • rpad:向右补齐,到指定长度,如果str的长度大于len,则返回值将缩短为len个右边字符。如果填充字符串为空字符,则返回值为null
  • regexp_replace:SELECT regexp_replace(‘100-200’, ‘(\d+)’, ‘num’)=‘num-num’,使用正则表达式匹配目标字符串,匹配成功后替换!

7.1.5 集合操作

  • size:集合(map和list)中元素的个数
  • map:定义Map
  • map_keys: 返回map中的key
  • map_values:返回map中的value
  • array:定义数组
  • array_contains:判断array中是否包含某个元素
  • sort_array:将array中的元素排序
  • struct:定义Struct集合

7.1.6 窗口和分析函数

官方文档地址:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+WindowingAndAnalytics。
oracle,sqlserver都提供了窗口函数,mysql从8.0开始提供窗口函数。窗口函数作用于一个数据行集合。窗口是标准的SQL术语,用来描述SQL语句内OVER从句划定的内容,这个内容就是窗口函数的作用域。而在OVER子句中,定义了窗口所覆盖的与当前行相关的数据行集、行的排序及其他的相关元素。

标准SQL对窗口函数的第一次支持是在SQL:1999的扩展文档中,当时,它们称为“OLAP”函数。从那以后,每次标准版本的修订都会增强对窗口函数的支持,直到现在的SQL:2003、SQL:2008、SQL:2011。最新的SQL标准版本,已经有了非常丰富和全面的窗口函数,显示出标准委员会对这一概念的坚定,以及从更多窗口函数和更多功能两个方面持续增强支持标准。

Hive支持的窗口和分析函数如下:
窗口函数

  • LEADLEAD (scalar_expression [,offset] [,default]),返回当前行的后offset行指定列的数据,可以指定默认值。
  • LAGLAG (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause),返回当前行的前offset行指定列的数据,可以指定默认值。
  • FIRST_VALUEFIRST_VALUE(列名,[false(默认)]),返回当前窗口指定列的第一个值,第二个参数如果为true,代表加入第一个值为null时,跳过空值,继续寻找
  • LAST_VALUELAST_VALUE(列名,[false(默认)]),返回当前窗口指定列的最后一个值,第二个参数如果为true,代表加入第一个值为null,跳过空值,继续寻找

OVER 从句
语法:function OVER(PARTITION BY col ORDER BY col window_clause)

  • 使用标准的聚合函数COUNT、SUM、MIN、MAX、AVG
  • 使用PARTITION BY(使用一个或多个原始数据类型的分区列)语句
  • 使用PARTITION BY(一个或多个基本数据类型的分区列)ORDER BY(一个或多个任意类型的排序列)语句
  • 使用窗口规范,窗口可以在窗口从句(window_clause)中单独定义,窗口规范支持以下格式:
    (ROWS | RANGE) BETWEEN (UNBOUNDED | [num]) PRECEDING AND ([num] PRECEDING | CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
    (ROWS | RANGE) BETWEEN CURRENT ROW AND (CURRENT ROW | (UNBOUNDED | [num]) FOLLOWING)
    (ROWS | RANGE) BETWEEN [num] FOLLOWING AND (UNBOUNDED | [num]) FOLLOWING
    

注意:

  1. ORDER BY后面缺少窗口从句条件,窗口规范默认是 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW(从第一行到当前行)。

  2. ORDER BY和窗口从句都缺失, 窗口规范默认是 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING(所有行)。

  3. OVER从句支持以下函数, 但是并不支持和窗口从句(window_clause)一起使用它们。
    Ranking函数: Rank, NTile, DenseRank, CumeDist, PercentRank
    LeadLag 函数。

分析函数
以下分析函数必须和窗口Over一起使用,但不支持和窗口从句(window_clause)一起使用:

  • RANK:允许并列,一旦有并列跳号。
  • ROW_NUMBER:行号,连续的,每个号之间差1。
  • DENSE_RANK:允许并列,一旦有并列不跳号。
  • CUME_DIST:从排序后的第一行到当前值之间的数据占整个数据集的百分比。
  • PERCENT_RANK:rank-1/ 总数据量-1。
  • NTILE:将数据集均分到n个组中,返回每条记录所在的组号。
hive (default)> select * from score;
score.name      score.subject   score.score
孙悟空  语文    87
孙悟空  数学    95
孙悟空  英语    68
大海    语文    94
大海    数学    56
大海    英语    84
宋宋    语文    64
宋宋    数学    86
宋宋    英语    84
婷婷    语文    65
婷婷    数学    85
婷婷    英语    78

hive (default)> select *,
			  > rank() over(order by score) rank,					-- 允许并列,一旦有并列跳号
			  > row_number() over(order by score) rownumber,		-- 行号,连续的,每个号之间差1
			  > dense_rank() over(order by score) denserank,		-- 允许并列,一旦有并列不跳号
			  > cume_dist() over(order by score) cumedist,			-- 从排序后的第一行到当前值之间的数据占整个数据集的百分比
			  > percent_rank() over(order by score) percentrank, 	-- rank-1/ 总数据量-1
			  > ntile(5) over() ntile								-- 将数据集均分到n个组中,返回每条记录所在的组号
			  > from score;
score.name      score.subject   score.score     rank    rownumber       denserank       cumedist        percentrank  ntile
孙悟空  数学    95      12      12      11      1.0     1.0     1
大海    语文    94      11      11      10      0.9166666666666666      0.9090909090909091      1
孙悟空  语文    87      10      10      9       0.8333333333333334      0.8181818181818182      1
宋宋    数学    86      9       9       8       0.75    0.7272727272727273      2
婷婷    数学    85      8       8       7       0.6666666666666666      0.6363636363636364      2
大海    英语    84      6       7       6       0.5833333333333334      0.45454545454545453     2
宋宋    英语    84      6       6       6       0.5833333333333334      0.45454545454545453     3
婷婷    英语    78      5       5       5       0.4166666666666667      0.36363636363636365     3
孙悟空  英语    68      4       4       4       0.3333333333333333      0.2727272727272727      4
婷婷    语文    65      3       3       3       0.25    0.18181818181818182     4
宋宋    语文    64      2       2       2       0.16666666666666666     0.09090909090909091     5
大海    数学    56      1       1       1       0.08333333333333333     0.0     5

Distinct(support in Hive 2.1.0 and later)

COUNT(DISTINCT a) OVER (PARTITION BY c)

Hive 2.2.0中在使用ORDER BY和窗口规范时开始支持distinct

COUNT(DISTINCT a) OVER (PARTITION BY c ORDER BY d ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING)

Over从句中使用聚合函数(support in Hive 2.1.0 and later)

SELECT rank() OVER (ORDER BY sum(b))
FROM T
GROUP BY a;

窗口函数和分组的区别
①如果使用group by,此时select后只能写group by后的字段和聚集函数中的字段。
②如果使用group by,可以执行去重,而partition by不去重。
③窗口函数是对窗口内的每条记录都使用函数计算一次。

7.2 自定义函数

用户自定义函数有三种:

(1)UDF(User-Defined-Function):一进一出。输入单个参数,返回单个结果。
(2)UDAF(User-Defined Aggregation Function):聚合函数,多进一出。传入一列多行的数据,返回一个结果,类似于:count、max、min。
(3)UDTF(User-Defined Table-Generating Functions):表格生成函数,一进多出。传入一个参数(集合类型),返回一个结果集,如lateral view explode。

自定义函数步骤:

  1. 创建一个Maven工程
  2. 导入依赖
    	<dependencies>
    			
    			<dependency>
    				<groupId>org.apache.hivegroupId>
    				<artifactId>hive-execartifactId>
    				<version>1.2.1version>
    			dependency>
    	dependencies>
    
  3. 创建类继承org.apache.hadoop.hive.ql.exec.UDF,编写evaluate函数,该函数会被Hive框架自动调用,函数可以重载只需函数名称固定,不可返回void,但是可以返回NULL。
    package com.yutao.hive;
    public class MyLower extends UDF {
           
    	
    	public String evaluate (final String s) {
           
    		if (s == null) {
           
    			return null;
    		}	
    		return s.toLowerCase();
    	}
    }
    
  4. 打成jar包上传到服务器${HIVE_HOME}/auxlib目录下(用户自定义jar目录,自动加载),也可以使用命令加载:
    hive (default)> add jar /opt/module/datas/udf.jar;
    
  5. 创建临时函数与开发好的java class关联
    # 创建临时函数,只当前连接可用,可去掉temporary创建永久函数
    hive (default)> create temporary function mylower as "com.yutao.hive.MyLower";
    
  6. 即可在hql中使用自定义的函数mylower
    # 函数具有库的范围,该函数只可在当前数据库可用
    hive (default)> select ename, MyLower(ename) lowername from emp;
    

8 案例

案例一:CASE WHEN

求每个部门男女各有多少人

hive (default)> select * from emp_sex;
emp_sex.name    emp_sex.dept_id emp_sex.sex
悟空    A       男
大海    A       男
宋宋    B       男
凤姐    A       女
婷姐    B       女
婷婷    B       女

hive (default)> select dept_id,
			  > sum(case sex when '男' then 1 else 0 end) male_count,
			  > sum(case sex when '女'  then 1 else 0 end) female_count 
			  > from emp_sex group by dept_id;
dept_id male_count      female_count
A       2       1
B       1       2

hive (default)> select dept_id,
			  > sum(if(sex='男',1,0)) male_count,
			  > sum(if(sex='女',1,0)) female_count 
			  > from emp_sex group by dept_id;
dept_id male_count      female_count
A       2       1
B       1       2

案例二:行转列(collect_set/collect_list)

hive (default)> select * from person_info;
person_info.name        person_info.constellation       person_info.blood_type
孙悟空  白羊座  A
大海    射手座  A
宋宋    白羊座  B
猪八戒  白羊座  A
芬姐    射手座  A
唐僧    白羊座  B
猪八戒  白羊座  A

hive (default)> select concat_ws(',',constellation,blood_type),
			  > concat_ws('|',collect_set(name)) 
			  > from person_info group by constellation,blood_type;
_c0     _c1
射手座,A        大海|芬姐
白羊座,A        孙悟空|猪八戒
白羊座,B        宋宋|唐僧

案例三:列转行(lateral view explode)

示例一:

hive (default)> select * from movie_info;
movie_info.movie        movie_info.category
《Lie to me》   ["悬疑","警匪","动作","心理","剧情"]
《战狼》        ["战争","动作","灾难"]
《疑犯追踪》    ["悬疑","动作","科幻","剧情"]

-- explode之后为1列12行,lateral view作用是逻辑上依然是1列三行,然后和同一行的movie做笛卡尔积
hive (default)> select movie,col from movie_info lateral view explode(category) tmp as col;
movie   col
《Lie to me》   悬疑
《Lie to me》   警匪
《Lie to me》   动作
《Lie to me》   心理
《Lie to me》   剧情
《战狼》        战争
《战狼》        动作
《战狼》        灾难
《疑犯追踪》    悬疑
《疑犯追踪》    动作
《疑犯追踪》    科幻
《疑犯追踪》    剧情

示例二:

hive (default)> select * from person_info2;
person_info2.names      person_info2.tags       person_info2.hobbys
["jack","tom","jerry"]  ["阳光男孩","肌肉男孩","直男"]  ["晒太阳","健身","说多喝热水"]
["marry","nancy"]       ["阳光女孩","肌肉女孩","腐女"]  ["晒太阳","健身","看有内涵的段子"]

hive (default)> select name,tag,hobby from person_info2 
			  > lateral view explode(names) tmp1 as name
              > lateral view explode(tags) tmp2 as tag
              > lateral view explode(hobbys) tmp3 as hobby;
name    tag     hobby
jack    阳光男孩        晒太阳
jack    阳光男孩        健身
jack    阳光男孩        说多喝热水
jack    肌肉男孩        晒太阳
jack    肌肉男孩        健身
jack    肌肉男孩        说多喝热水
jack    直男    晒太阳
jack    直男    健身
jack    直男    说多喝热水
tom     阳光男孩        晒太阳
tom     阳光男孩        健身
tom     阳光男孩        说多喝热水
tom     肌肉男孩        晒太阳
tom     肌肉男孩        健身
tom     肌肉男孩        说多喝热水
tom     直男    晒太阳
tom     直男    健身
tom     直男    说多喝热水
jerry   阳光男孩        晒太阳
jerry   阳光男孩        健身
jerry   阳光男孩        说多喝热水
jerry   肌肉男孩        晒太阳
jerry   肌肉男孩        健身
jerry   肌肉男孩        说多喝热水
jerry   直男    晒太阳
jerry   直男    健身
jerry   直男    说多喝热水
marry   阳光女孩        晒太阳
marry   阳光女孩        健身
marry   阳光女孩        看有内涵的段子
marry   肌肉女孩        晒太阳
marry   肌肉女孩        健身
marry   肌肉女孩        看有内涵的段子
marry   腐女    晒太阳
marry   腐女    健身
marry   腐女    看有内涵的段子
nancy   阳光女孩        晒太阳
nancy   阳光女孩        健身
nancy   阳光女孩        看有内涵的段子
nancy   肌肉女孩        晒太阳
nancy   肌肉女孩        健身
nancy   肌肉女孩        看有内涵的段子
nancy   腐女    晒太阳
nancy   腐女    健身
nancy   腐女    看有内涵的段子

案例四:窗口函数

hive (default)> select * from business;
business.name   business.orderdate      business.cost
jack    2017-01-01      10
tony    2017-01-02      15
jack    2017-02-03      23
tony    2017-01-04      29
jack    2017-01-05      46
jack    2017-04-06      42
tony    2017-01-07      50
jack    2017-01-08      55
mart    2017-04-08      62
mart    2017-04-09      68
neil    2017-05-10      12
mart    2017-04-11      75
neil    2017-06-12      80
mart    2017-04-13      94

(1)查询在2017年4月份购买过的顾客及总人数

-- 传统写法: 效率低
hive (default)> with tmp as (select name from business where year(orderdate)='2017' and month(orderdate)=4 group by name) 
			  > select name,totalCount from (select count(1) totalCount from tmp) tmp1 join tmp;
name    totalcount
jack    2
mart    2

-- 窗口函数写法(解释:分组完成后,count函数正常是统计每个分组内的条数,
-- over的效果是指定前面的函数的统计范围(窗口大小),下面的over指定的范围是当前行的上无边界和下无边界=全部)
hive (default)> select name,
			  > count(*) over(rows between UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) totalcount
			  > from business where substring(orderdate,1,7)='2017-04' group by name;
name    totalcount
jack    2
mart    2			  

(2)查询顾客的购买明细及月购买总额

-- 不存在ORDER BY和窗口从句时,窗口从句默认为`ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING`,可以省略
hive (default)> select name,orderdate,cost,
			  > sum(cost) over(partition by name,substring(orderdate,1,7) ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) monthCost 
			  > from business;
name    orderdate       cost    monthCost
jack    2017-01-05      46      111
jack    2017-01-08      55      111
jack    2017-01-01      10      111
jack    2017-02-03      23      23
jack    2017-04-06      42      42
mart    2017-04-13      94      299
mart    2017-04-11      75      299
mart    2017-04-09      68      299
mart    2017-04-08      62      299
neil    2017-05-10      12      12
neil    2017-06-12      80      80
tony    2017-01-04      29      94
tony    2017-01-02      15      94
tony    2017-01-07      50      94

(3)查询顾客的购买明细要将cost按照日期进行累加

-- 存在ORDER BY时,窗口从句默认为`RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW`,可省略
hive (default)> select name,orderdate,cost,
			  > sum(cost) over(PARTITION BY name ORDER BY orderdate RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW) as addUp 
			  > from business;
name    orderdate       cost    addup
jack    2017-01-01      10      10
jack    2017-01-05      46      56
jack    2017-01-08      55      111
jack    2017-02-03      23      134
jack    2017-04-06      42      176
mart    2017-04-08      62      62
mart    2017-04-09      68      130
mart    2017-04-11      75      205
mart    2017-04-13      94      299
neil    2017-05-10      12      12
neil    2017-06-12      80      92
tony    2017-01-02      15      15
tony    2017-01-04      29      44
tony    2017-01-07      50      94

(4)查询顾客的购买明细及顾客上次的购买时间

hive (default)> select name,orderdate,cost,
			  > LAG(orderdate,1,'未找到数据') over(PARTITION BY name ORDER BY orderdate) pre_orderdate 
			  > from business;
name    orderdate       cost    pre_orderdate
jack    2017-01-01      10      未找到数据
jack    2017-01-05      46      2017-01-01
jack    2017-01-08      55      2017-01-05
jack    2017-02-03      23      2017-01-08
jack    2017-04-06      42      2017-02-03
mart    2017-04-08      62      未找到数据
mart    2017-04-09      68      2017-04-08
mart    2017-04-11      75      2017-04-09
mart    2017-04-13      94      2017-04-11
neil    2017-05-10      12      未找到数据
neil    2017-06-12      80      2017-05-10
tony    2017-01-02      15      未找到数据
tony    2017-01-04      29      2017-01-02
tony    2017-01-07      50      2017-01-04

(5)查询顾客的购买明细及顾客下次的购买时间

hive (default)> select name,orderdate,cost,
			  > LEAD(orderdate,1,'未找到数据') over(PARTITION BY name ORDER BY orderdate) next_orderdate
			  > from business;
name    orderdate       cost    next_orderdate
jack    2017-01-01      10      2017-01-05
jack    2017-01-05      46      2017-01-08
jack    2017-01-08      55      2017-02-03
jack    2017-02-03      23      2017-04-06
jack    2017-04-06      42      未找到数据
mart    2017-04-08      62      2017-04-09
mart    2017-04-09      68      2017-04-11
mart    2017-04-11      75      2017-04-13
mart    2017-04-13      94      未找到数据
neil    2017-05-10      12      2017-06-12
neil    2017-06-12      80      未找到数据
tony    2017-01-02      15      2017-01-04
tony    2017-01-04      29      2017-01-07
tony    2017-01-07      50      未找到数据

(6)查询顾客的购买明细及顾客本月第一次购买的时间

hive (default)> select name,orderdate,cost,
			  > FIRST_VALUE(orderdate,true) over(partition by name,substring(orderdate,1,7) order by orderdate) firstorderdate 
			  > from business;
name    orderdate       cost    firstorderdate
jack    2017-01-01      10      2017-01-01
jack    2017-01-05      46      2017-01-01
jack    2017-01-08      55      2017-01-01
jack    2017-02-03      23      2017-02-03
jack    2017-04-06      42      2017-04-06
mart    2017-04-08      62      2017-04-08
mart    2017-04-09      68      2017-04-08
mart    2017-04-11      75      2017-04-08
mart    2017-04-13      94      2017-04-08
neil    2017-05-10      12      2017-05-10
neil    2017-06-12      80      2017-06-12
tony    2017-01-02      15      2017-01-02
tony    2017-01-04      29      2017-01-02
tony    2017-01-07      50      2017-01-02

(7)查询顾客的购买明细及顾客本月最后一次购买的时间

hive (default)> select name,orderdate,cost,
			  > LAST_VALUE(orderdate,true) over(partition by name,substring(orderdate,1,7) order by orderdate  ROWS BETWEEN CURRENT ROW AND UNBOUNDED FOLLOWING) lastorderdate 
			  > from business;
name    orderdate       cost    lastorderdate
jack    2017-01-01      10      2017-01-08
jack    2017-01-05      46      2017-01-08
jack    2017-01-08      55      2017-01-08
jack    2017-02-03      23      2017-02-03
jack    2017-04-06      42      2017-04-06
mart    2017-04-08      62      2017-04-13
mart    2017-04-09      68      2017-04-13
mart    2017-04-11      75      2017-04-13
mart    2017-04-13      94      2017-04-13
neil    2017-05-10      12      2017-05-10
neil    2017-06-12      80      2017-06-12
tony    2017-01-02      15      2017-01-07
tony    2017-01-04      29      2017-01-07
tony    2017-01-07      50      2017-01-07

(8)查询顾客的购买明细及顾客最近三次(当前和之前两次 或 当前+前一次+后一次)cost花费

-- 当前和之前两次
hive (default)> select name,orderdate,cost,
			  > sum(cost) over(partition by name order by orderdate ROWS BETWEEN 2 PRECEDING AND CURRENT ROW) recentcost 
			  > from business;
name    orderdate       cost    recentcost
jack    2017-01-01      10      10
jack    2017-01-05      46      56
jack    2017-01-08      55      111
jack    2017-02-03      23      124
jack    2017-04-06      42      120
mart    2017-04-08      62      62
mart    2017-04-09      68      130
mart    2017-04-11      75      205
mart    2017-04-13      94      237
neil    2017-05-10      12      12
neil    2017-06-12      80      92
tony    2017-01-02      15      15
tony    2017-01-04      29      44
tony    2017-01-07      50      94

-- 当前+前一次+后一次
hive (default)> select name,orderdate,cost,sum(cost) 
			  > over(partition by name order by orderdate ROWS BETWEEN 1 PRECEDING AND 1 FOLLOWING) recentcost 
			  > from business;
name    orderdate       cost    recentcost
jack    2017-01-01      10      56
jack    2017-01-05      46      111
jack    2017-01-08      55      124
jack    2017-02-03      23      120
jack    2017-04-06      42      65
mart    2017-04-08      62      130
mart    2017-04-09      68      205
mart    2017-04-11      75      237
mart    2017-04-13      94      169
neil    2017-05-10      12      92
neil    2017-06-12      80      92
tony    2017-01-02      15      44
tony    2017-01-04      29      94
tony    2017-01-07      50      79

(9)查询前20%时间的订单信息

hive (default)> select name,orderdate,cost from 
			  > (select name,orderdate,cost,cume_dist() over(order by orderdate) cumedist from business) tmp 
			  > where cumedist<0.2;
name    orderdate       cost
jack    2017-01-01      10
tony    2017-01-02      15

案例五:排名函数

hive (default)> select * from score;
score.name      score.subject   score.score
孙悟空  语文    87
孙悟空  数学    95
孙悟空  英语    68
大海    语文    94
大海    数学    56
大海    英语    84
宋宋    语文    64
宋宋    数学    86
宋宋    英语    84
婷婷    语文    65
婷婷    数学    85
婷婷    英语    78

(1)按照科目进行排名

hive (default)> select name,subject,score,rank() over(partition by subject order by score desc) rank from score;
name    subject score   rank
孙悟空  数学    95      1
宋宋    数学    86      2
婷婷    数学    85      3
大海    数学    56      4
宋宋    英语    84      1
大海    英语    84      1
婷婷    英语    78      3
孙悟空  英语    68      4
大海    语文    94      1
孙悟空  语文    87      2
婷婷    语文    65      3
宋宋    语文    64      4

(2)给每个学生的总分进行排名

hive (default)> select name,sum(score) totalscore,
			  > rank() over(order by sum(score) desc ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) rank
			  > from score group by name;
name    totalscore      rank
孙悟空  250     1
宋宋    234     2
大海    234     2
婷婷    228     4

(3)求每个学生的成绩明细及给每个学生的总分和总分排名

hive (default)> select name,
			  > concat_ws('\t',collect_list(concat(subject,':',score))) subjects,
			  > sum(score) totalscore,
			  > rank() over(order by sum(score) desc) rank 
			  > from score group by name;
name    subjects        totalscore      rank
孙悟空  语文:87 数学:95 英语:68 250     1
宋宋    语文:64 数学:86 英语:84 234     2
大海    语文:94 数学:56 英语:84 234     2
婷婷    语文:65 数学:85 英语:78 228     4

(4)只查询每个科目的成绩的前2名

hive (default)> select * from 
			  > (select name,subject,score,rank() over(partition by subject order by score desc) rank from score) tmp 
			  > where rank<=2;
tmp.name        tmp.subject     tmp.score       tmp.rank
孙悟空  数学    95      1
宋宋    数学    86      2
大海    英语    84      1
宋宋    英语    84      1
大海    语文    94      1
孙悟空  语文    87      2

(5)查询学生成绩明细,并显示当前科目最高分

-- 第一种写法
hive (default)> select name,subject,score,max(score) over(partition by subject) maxscore from score;
-- 第二种写法
hive (default)> select *,FIRST_VALUE(score) over(partition by subject order by score desc) maxscore from score;
-- 第三种写法
hive (default)> select *,LAST_VALUE(score) over(partition by subject order by score ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) maxscore from score;

name    subject score   maxscore
孙悟空  数学    95      95
宋宋    数学    86      95
婷婷    数学    85      95
大海    数学    56      95
宋宋    英语    84      84
大海    英语    84      84
婷婷    英语    78      84
孙悟空  英语    68      84
大海    语文    94      94
孙悟空  语文    87      94
婷婷    语文    65      94
宋宋    语文    64      94

(6)查询学生成绩,并显示当前科目最低分

-- 第一种写法
hive (default)> select name,subject,score,min(score) over(partition by subject) maxscore from score;
-- 第二种写法
hive (default)> select *,FIRST_VALUE(score) over(partition by subject order by score) minscore from score;
-- 第三中写法
hive (default)> select *,LAST_VALUE(score) over(partition by subject order by score DESC ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) minscore from score;
score.name      score.subject   score.score     minscore
孙悟空  数学    95      56
宋宋    数学    86      56
婷婷    数学    85      56
大海    数学    56      56
宋宋    英语    84      68
大海    英语    84      68
婷婷    英语    78      68
孙悟空  英语    68      68
大海    语文    94      64
孙悟空  语文    87      64
婷婷    语文    65      64
宋宋    语文    64      64

案例六:蚂蚁森林种树

-- plant_id:树苗id,plant_name:树苗名称,low_carbon:领取需消耗能量
hive (default)> select * from plant_carbon;
plant_carbon.plant_id   plant_carbon.plant_name plant_carbon.low_carbon
p001    梭梭树  17
p002    沙柳    19
p003    樟子树  146
p004    胡杨    215

-- user_id:用户id,data_dt:领取日期,user_low_carbon:用户领取能量
hive (default)> select * from user_low_carbon;
user_low_carbon.user_id user_low_carbon.data_dt user_low_carbon.low_carbon
u_001   2017/1/1        10
u_001   2017/1/2        150
u_001   2017/1/2        110
u_001   2017/1/2        10
u_001   2017/1/4        50
u_001   2017/1/4        10
u_001   2017/1/6        45
u_001   2017/1/6        90
u_002   2017/1/1        10
u_002   2017/1/2        150
u_002   2017/1/2        70
u_002   2017/1/3        30
u_002   2017/1/3        80
u_002   2017/1/4        150
u_002   2017/1/5        101
u_002   2017/1/6        68
u_003   2017/1/1        20
u_003   2017/1/2        10
u_003   2017/1/2        150
u_003   2017/1/3        160
u_003   2017/1/4        20
u_003   2017/1/5        120
u_003   2017/1/6        20
u_003   2017/1/7        10
u_003   2017/1/7        110
u_004   2017/1/1        110
u_004   2017/1/2        20
u_004   2017/1/2        50
u_004   2017/1/3        120
u_004   2017/1/4        30
u_004   2017/1/5        60
u_004   2017/1/6        120
u_004   2017/1/7        10
u_004   2017/1/7        120
u_005   2017/1/1        80
u_005   2017/1/2        50
u_005   2017/1/2        80
u_005   2017/1/3        180
u_005   2017/1/4        180
u_005   2017/1/4        10
u_005   2017/1/5        80
u_005   2017/1/6        280
u_005   2017/1/7        80
u_005   2017/1/7        80
u_006   2017/1/1        40
u_006   2017/1/2        40
u_006   2017/1/2        140
u_006   2017/1/3        210
u_006   2017/1/3        10
u_006   2017/1/4        40
u_006   2017/1/5        40
u_006   2017/1/6        20
u_006   2017/1/7        50
u_006   2017/1/7        240
u_007   2017/1/1        130
u_007   2017/1/2        30
u_007   2017/1/2        330
u_007   2017/1/3        30
u_007   2017/1/4        530
u_007   2017/1/5        30
u_007   2017/1/6        230
u_007   2017/1/7        130
u_007   2017/1/7        30
u_008   2017/1/1        160
u_008   2017/1/2        60
u_008   2017/1/2        60
u_008   2017/1/3        60
u_008   2017/1/4        260
u_008   2017/1/5        360
u_008   2017/1/6        160
u_008   2017/1/7        60
u_008   2017/1/7        60
u_009   2017/1/1        70
u_009   2017/1/2        70
u_009   2017/1/2        70
u_009   2017/1/3        170
u_009   2017/1/4        270
u_009   2017/1/5        70
u_009   2017/1/6        70
u_009   2017/1/7        70
u_009   2017/1/7        70
u_010   2017/1/1        90
u_010   2017/1/2        90
u_010   2017/1/2        90
u_010   2017/1/3        90
u_010   2017/1/4        90
u_010   2017/1/4        80
u_010   2017/1/5        90
u_010   2017/1/5        90
u_010   2017/1/6        190
u_010   2017/1/7        90
u_010   2017/1/7        90
u_011   2017/1/1        110
u_011   2017/1/2        100
u_011   2017/1/2        100
u_011   2017/1/3        120
u_011   2017/1/4        100
u_011   2017/1/5        100
u_011   2017/1/6        100
u_011   2017/1/7        130
u_011   2017/1/7        100
u_012   2017/1/1        10
u_012   2017/1/2        120
u_012   2017/1/2        10
u_012   2017/1/3        10
u_012   2017/1/4        50
u_012   2017/1/5        10
u_012   2017/1/6        20
u_012   2017/1/7        10
u_012   2017/1/7        10
u_013   2017/1/1        50
u_013   2017/1/2        150
u_013   2017/1/2        50
u_013   2017/1/3        150
u_013   2017/1/4        550
u_013   2017/1/5        350
u_013   2017/1/6        50
u_013   2017/1/7        20
u_013   2017/1/7        60
u_014   2017/1/1        220
u_014   2017/1/2        120
u_014   2017/1/2        20
u_014   2017/1/3        20
u_014   2017/1/4        20
u_014   2017/1/5        250
u_014   2017/1/6        120
u_014   2017/1/7        270
u_014   2017/1/7        20
u_015   2017/1/1        10
u_015   2017/1/2        20
u_015   2017/1/2        10
u_015   2017/1/3        10
u_015   2017/1/4        20
u_015   2017/1/5        70
u_015   2017/1/6        10
u_015   2017/1/7        80
u_015   2017/1/7        60

(1)蚂蚁森林植物申领统计

问题:假设2017年1月1日开始记录低碳数据(user_low_carbon),假设2017年10月1日之前满足申领条件的用户都申领了一颗p004-胡杨,剩余的能量全部用来领取“p002-沙柳”。统计在10月1日累计申领“p002-沙柳”排名前10的用户信息;以及他比后一名多领了几颗沙柳。
得到的统计结果如下表样式:
user_id plant_count less_count
u_101—>1000—>100
u_088—>900—>400
u_103—>500—>xxx…

hive (default)> with p002_carbon as (select low_carbon from plant_carbon where plant_id='p002'),
			  > p004_carbon as (select low_carbon from plant_carbon where plant_id='p004'),
			  > tmp as (select user_id,sum(low_carbon) lowcarbon from user_low_carbon where regexp_replace(data_dt,'/','-')>='2017-01-01' and regexp_replace(data_dt,'/','-')<'2017-10-01' group by user_id)
			  > select tmp1.user_id,tmp1.plant_count,tmp1.plant_count-LEAD(tmp1.plant_count,1) over(order by plant_count desc) less_count 
			  > from (select user_id,case when tmp.lowcarbon>=p004_carbon.low_carbon then floor((tmp.lowcarbon-p004_carbon.low_carbon)/p002_carbon.low_carbon) else floor(tmp.lowcarbon/p002_carbon.low_carbon) end plant_count 
			  > from tmp join p004_carbon join p002_carbon) tmp1 limit 10;

tmp1.user_id    tmp1.plant_count        less_count
u_007   66      3
u_013   63      10
u_008   53      7
u_005   46      1
u_010   45      1
u_014   44      5
u_011   39      2
u_009   37      5
u_006   32      9
u_002   23      1

(2)蚂蚁森林低碳用户排名分析

问题:查询user_low_carbon表中每日流水记录,条件为:
用户在2017年,连续三天(或以上)的天数里,
每天减少碳排放(low_carbon)都超过100g的用户低碳流水。
需要查询返回满足以上条件的user_low_carbon表中的记录流水。

hive (default)> with tmp as (select user_id,regexp_replace(data_dt,'/','-') data_dt,sum(low_carbon) carbonPerDay from user_low_carbon where year(regexp_replace(data_dt,'/','-'))='2017' group by user_id,data_dt having carbonPerDay>=100)
			  > select ulc.* from user_low_carbon ulc join
			  > (select user_id,regexp_replace(data_dt,'-','/') data_dt,carbonPerDay from
			  > (select user_id,data_dt,carbonPerDay,
			  > datediff(data_dt,LAG(data_dt,2,'1970-01-01') over(partition by user_id order by data_dt)) preTwoDiff,
			  > datediff(data_dt,LAG(data_dt,1,'1970-01-01') over(partition by user_id order by data_dt)) preOneDiff,
			  > datediff(data_dt,LEAD(data_dt,1,'1970-01-01') over(partition by user_id order by data_dt)) nextOneDiff,
			  > datediff(data_dt,LEAD(data_dt,2,'1970-01-01') over(partition by user_id order by data_dt)) nextTwoDiff
			  > from tmp) tmp1
			  > where (tmp1.preTwoDiff=2 and tmp1.preOneDiff=1) or (tmp1.preOneDiff=1 and tmp1.nextOneDiff=-1) or (tmp1.nextOneDiff=-1 and tmp1.nextTwoDiff=-2)) tmp2 on ulc.user_id=tmp2.user_id and ulc.data_dt=tmp2.data_dt;

ulc.user_id     ulc.data_dt     ulc.low_carbon
u_002   2017/1/2        150
u_002   2017/1/2        70
u_002   2017/1/3        30
u_002   2017/1/3        80
u_002   2017/1/4        150
u_002   2017/1/5        101
u_005   2017/1/2        50
u_005   2017/1/2        80
u_005   2017/1/3        180
u_005   2017/1/4        180
u_005   2017/1/4        10
u_008   2017/1/4        260
u_008   2017/1/5        360
u_008   2017/1/6        160
u_008   2017/1/7        60
u_008   2017/1/7        60
u_009   2017/1/2        70
u_009   2017/1/2        70
u_009   2017/1/3        170
u_009   2017/1/4        270
u_010   2017/1/4        90
u_010   2017/1/4        80
u_010   2017/1/5        90
u_010   2017/1/5        90
u_010   2017/1/6        190
u_010   2017/1/7        90
u_010   2017/1/7        90
u_011   2017/1/1        110
u_011   2017/1/2        100
u_011   2017/1/2        100
u_011   2017/1/3        120
u_011   2017/1/4        100
u_011   2017/1/5        100
u_011   2017/1/6        100
u_011   2017/1/7        130
u_011   2017/1/7        100
u_013   2017/1/2        150
u_013   2017/1/2        50
u_013   2017/1/3        150
u_013   2017/1/4        550
u_013   2017/1/5        350
u_014   2017/1/5        250
u_014   2017/1/6        120
u_014   2017/1/7        270
u_014   2017/1/7        20

你可能感兴趣的:(big,data,hive,大数据,java)