#查看系统自带的函数
hive (default)> show functions;
#显示自带的函数的用法
hive (default)> desc function upper;
#详细显示自带的函数的用法
hive (default)> desc function extended upper;
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
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’) mnround
:四舍五入ceil
:向上取整floor
:向下取整upper
:转大写lower
:转小写length
:长度trim
:前后去空格lpad
:向左补齐,到指定长度,如果str的长度大于len,则返回值将缩短为len个左边字符。如果填充字符串为空字符,则返回值为nullrpad
:向右补齐,到指定长度,如果str的长度大于len,则返回值将缩短为len个右边字符。如果填充字符串为空字符,则返回值为nullregexp_replace
:SELECT regexp_replace(‘100-200’, ‘(\d+)’, ‘num’)=‘num-num’,使用正则表达式匹配目标字符串,匹配成功后替换!size
:集合(map和list)中元素的个数map
:定义Mapmap_keys
: 返回map中的keymap_values
:返回map中的valuearray
:定义数组array_contains
:判断array中是否包含某个元素sort_array
:将array中的元素排序struct
:定义Struct集合官方文档地址: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支持的窗口和分析函数如下:
窗口函数
LEAD
:LEAD (scalar_expression [,offset] [,default])
,返回当前行的后offset行指定列的数据,可以指定默认值。LAG
:LAG (scalar_expression [,offset] [,default]) OVER ([query_partition_clause] order_by_clause)
,返回当前行的前offset行指定列的数据,可以指定默认值。FIRST_VALUE
:FIRST_VALUE(列名,[false(默认)])
,返回当前窗口指定列的第一个值,第二个参数如果为true,代表加入第一个值为null时,跳过空值,继续寻找LAST_VALUE
:LAST_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(一个或多个任意类型的排序列)
语句(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
注意:
当ORDER BY
后面缺少窗口从句条件,窗口规范默认是 RANGE BETWEEN UNBOUNDED PRECEDING AND CURRENT ROW
(从第一行到当前行)。
当ORDER BY
和窗口从句都缺失, 窗口规范默认是 ROWS BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING
(所有行)。
OVER
从句支持以下函数, 但是并不支持和窗口从句(window_clause)一起使用它们。
Ranking函数: Rank, NTile, DenseRank, CumeDist, PercentRank
。
Lead
和 Lag
函数。
分析函数
以下分析函数必须和窗口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不去重。
③窗口函数是对窗口内的每条记录都使用函数计算一次。
用户自定义函数有三种:
(1)UDF(User-Defined-Function):一进一出。输入单个参数,返回单个结果。
(2)UDAF(User-Defined Aggregation Function):聚合函数,多进一出。传入一列多行的数据,返回一个结果,类似于:count、max、min。
(3)UDTF(User-Defined Table-Generating Functions):表格生成函数,一进多出。传入一个参数(集合类型),返回一个结果集,如lateral view explode。
自定义函数步骤:
<dependencies>
<dependency>
<groupId>org.apache.hivegroupId>
<artifactId>hive-execartifactId>
<version>1.2.1version>
dependency>
dependencies>
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();
}
}
${HIVE_HOME}/auxlib
目录下(用户自定义jar目录,自动加载),也可以使用命令加载:hive (default)> add jar /opt/module/datas/udf.jar;
# 创建临时函数,只当前连接可用,可去掉temporary创建永久函数
hive (default)> create temporary function mylower as "com.yutao.hive.MyLower";
# 函数具有库的范围,该函数只可在当前数据库可用
hive (default)> select ename, MyLower(ename) lowername from emp;
求每个部门男女各有多少人
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
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 宋宋|唐僧
示例一:
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
-- 传统写法: 效率低
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
-- 不存在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
-- 存在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
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
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 未找到数据
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
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
-- 当前和之前两次
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
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
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
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
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
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
-- 第一种写法
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
-- 第一种写法
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
问题:假设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
问题:查询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