hive(四)函数详解1(内有窗口函数详解)

目录标题

  • 1.常用查询函数
    • 1.1 空字段赋值
    • 1.2 时间类
    • 1.3 CASE WHEN
    • 1.4 行转列
    • 1.5 列转行
    • 1.6 窗口函数
    • 1.7 Rank
  • 2.课堂练习
    • 2.1 案例一
    • 2.2 案例二

1.常用查询函数

1.1 空字段赋值

1)函数说明
NVL:给值为 NULL 的数据赋值,它的格式是 NVL( string1,replace_with)。它的功能是如果string1 为 NULL,则 NVL 函数返回 replace_with 的值,否则返回 string1 的值,如果两个参数都为 NULL ,则返回 NULL。
2)数据准备:采用员工表
3)查询:如果员工的 comm 为 NULL,则用-1 代替

hive (default)> select nvl(comm,-1) from emp;

4)查询:如果员工的 comm 为 NULL,则用领导 id 代替

hive (default)> select nvl(comm,mgr) from emp;

1.2 时间类

1)date_format:格式化时间

hive (default)> select date_format('2020-07-26','yyyy-MM-dd');

hive(四)函数详解1(内有窗口函数详解)_第1张图片

2)date_add:时间跟天数相加

hive (default)> select date_add('2020-07-26',5);

hive(四)函数详解1(内有窗口函数详解)_第2张图片

hive (default)> select date_add('2020-07-26',-35);

在这里插入图片描述

3)date_sub:时间跟天数相减(这个记上面那个加就行了)

4)datediff:两个时间相减(前减后)

hive (default)> select datediff('2019-06-29','2019-06-24');

在这里插入图片描述

hive (default)> select datediff('2019-06-24','2019-06-29');

hive(四)函数详解1(内有窗口函数详解)_第3张图片
注意上面时间格式只有‘yyyy-MM-dd’,中间分隔符是‘-’,我们是否可以更改呢?例如更改为斜杠‘/’
我们试一下:(regexp_replace()这个函数用作替换)

select regexp_replace('2020/07/26','/','-');

1.3 CASE WHEN

1.数据准备
hive(四)函数详解1(内有窗口函数详解)_第4张图片
2.需求
求出不同部门男女各多少人。结果如下:

A 2 1
B 1 2

3.创建本地 emp_sex.txt,添加数据

悟空	A	男
大海	A	男
宋宋	B	男
凤姐	A	女
婷姐	B	女
婷婷	B	女

4.创建 hive 表并导入数据

create table emp_sex(
name string, 
dept_id string, 
sex string) 
row format delimited fields terminated by "\t";

load data local inpath '/opt/module/data/emp_sex.txt' into table emp_sex;

全表查询
hive(四)函数详解1(内有窗口函数详解)_第5张图片

5.按需求查询数据

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;

在这里插入图片描述
或者这样也行

select 
 dept_id,
 sum(if(sex='男',1,0)) male_count,
 sum(if(sex='女',1,0)) female_count
from 
 emp_sex
group by
 dept_id;

结果一样
在这里插入图片描述

  • 切记在Linux上写sql语句,不要用tab,因为tab表示提醒
  • 取别名不要用中文

1.4 行转列

1.相关函数说明

  • CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;
  • CONCAT_WS(separator, str1, str2,…):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔
    符将被加到被连接的字符串之间;
  • COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生 array 类型字段。(聚合)

2.数据准备

name	constellation	blood_type
孙悟空	白羊座	A
大海	射手座	A
宋宋	白羊座	B
猪八戒 	白羊座	A
凤姐	射手座	A

3.需求
把星座和血型一样的人归类到一起。结果如下:

射手座,A 大海|凤姐
白羊座,A 孙悟空|猪八戒
白羊座,B 宋宋

4.创建本地 constellation.txt,导入数据

[liuyongjun@hadoop102 data]$ vim  constellation.txt

5.创建 hive 表并导入数据

create table person_info(
 name string, 
 constellation string, 
 blood_type string) 
row format delimited fields terminated by '\t';
load data local inpath "/opt/module/data/constellation.txt" into 
table person_info;

6.按需求查询数据
逐渐来:
第一步:

select
 concat(constellation,',',blood_type) constellation_blood_type,
 name
from 
 person_info;

在这里插入图片描述
第二步:

select 
 constellation_blood_type,
 concat_ws('|',collect_set(name))
from 
 (select
 concat(constellation,',',blood_type) constellation_blood_type,
 name
from 
 person_info) t1
group by constellation_blood_type;

在这里插入图片描述

1.5 列转行

1.函数说明
EXPLODE(col):将 hive 一列中复杂的 array 或者 map 结构拆分成多行。
LATERAL VIEW
用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias
解释:用于和 split, explode 等 UDTF 一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。
2.数据准备

movie category
《疑犯追踪》 悬疑,动作,科幻,剧情
《Lie to me》 悬疑,警匪,动作,心理,剧情
《战狼 2》 战争,动作,灾难

3.需求
将电影分类中的数组数据展开。结果如下:

《疑犯追踪》 悬疑
《疑犯追踪》 动作
《疑犯追踪》 科幻
《疑犯追踪》 剧情
《Lie to me》 悬疑
《Lie to me》 警匪
《Lie to me》 动作
《Lie to me》 心理
《Lie to me》 剧情
《战狼 2》 战争
《战狼 2》 动作
《战狼 2》 灾难

4.创建本地 movie.txt,导入数据

《疑犯追踪》	悬疑,动作,科幻,剧情
《Lie to me》	悬疑,警匪,动作,心理,剧情
《战狼 2》	战争,动作,灾难

5.创建 hive 表并导入数据

create table movie_info(
 movie string,
 category array)
row format delimited fields terminated by '\t'
collection items terminated by ',';
load data local inpath "/opt/module/data/movie.txt" into table movie_info;

6.按需求查询数据

select
 movie,
 category_name
from
 movie_info lateral view explode(category) table_tmp as category_name;

hive(四)函数详解1(内有窗口函数详解)_第6张图片

1.6 窗口函数

1.相关函数说明
OVER():指定分析函数工作的数据窗口大小,这个数据窗口大小可能会随着行的变化而变化;
CURRENT ROW:当前行;
n PRECEDING:往前 n 行数据;
n FOLLOWING:往后 n 行数据;
UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点,UNBOUNDED FOLLOWING 表示到后面的终点;
LAG(col,n):往前 n 行数据;
LEAD(col,n):往后 n 行数据;
NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从 1 开始,对于每一行,NTILE 返回此行所属的组的编号。注意:n 必须为 int 类型
2.数据准备:name,orderdate,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

3.需求
(1)查询在 2017 年 4 月份购买过的顾客及总人数
(2)查询顾客的购买明细及购买总额
(3)上述的场景,要将 cost 按照日期进行累加
(4)查询顾客上次的购买时间
(5)查询前 20%时间的订单信息
4.创建本地 business.txt,导入数据

[liuyongjun@hadoop102 data]$ vim business.txt

hive(四)函数详解1(内有窗口函数详解)_第7张图片

5.创建 hive 表并导入数据

create table business(
 name string,
 orderdate string,
 cost int) 
row format delimited fields terminated by ',';
load data local inpath "/opt/module/data/business.txt" into table business;

6.按需求查询数据
(1)查询在 2017 年 4 月份购买过的顾客及总人数
首先没加窗口函数

select name,count(*) 
from business 
where substring(orderdate,1,7)='2017-04'
group by name;

在这里插入图片描述
很明显,这个需求是每个人购买的次数
而需求是四月购买的总人数
于是加上over()窗口函数

select name,count(*) over()
from business 
where substring(orderdate,1,7)='2017-04'
group by name;

在这里插入图片描述

这样over就起作用了,起的什么作用呢,其实,over必须跟在聚合函数后面,起到开窗的作用,首先第一点就是开了一个数据集,给前面的聚合函数使用;第二点数据集被划分为一段一段的几部分;第三点说白了开窗函数(注意:没有参数的开窗函数是给每一条数据都开了窗口)的加入就是按name进行分组计算之后,再对计算后的结果进行聚合计算

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

select name,orderdate,cost,sum(cost) over(partition by 
month(orderdate)) 
from business;

hive(四)函数详解1(内有窗口函数详解)_第8张图片

(3)上述的场景,要将 cost 按照日期进行累加

select orderdate,cost,sum(cost) over(order by orderdate) --逐行相加
from business;

hive(四)函数详解1(内有窗口函数详解)_第9张图片
扩展:

select name,orderdate,cost,
sum(cost) over() as sample1,--所有行相加
sum(cost) over(partition by name) as sample2,--按 name 分组,组内数据相加
sum(cost) over(partition by name order by orderdate) as sample3,--按 name 分组,组内数据累加
sum(cost) over(partition by name order by orderdate rows between
UNBOUNDED PRECEDING and current row ) as sample4 ,--和 sample3 一 样,由起点到当前行的聚合
sum(cost) over(partition by name order by orderdate rows between 
1 PRECEDING and current row) as sample5, --当前行和前面一行做聚合
sum(cost) over(partition by name order by orderdate rows between 
1 PRECEDING AND 1 FOLLOWING ) as sample6,--当前行和前边一行及后面一行
sum(cost) over(partition by name order by orderdate rows between 
current row and UNBOUNDED FOLLOWING ) as sample7 --当前行及后面所有行
from business;

hive(四)函数详解1(内有窗口函数详解)_第10张图片
注意: partition by …order by可以用distribute by … sort by 代替
(4)查看顾客上次的购买时间

select name,orderdate,cost,
lag(orderdate,1,'1900-01-01') over(partition by name order by 
orderdate ) as time1, lag(orderdate,2) over (partition by name 
order by orderdate) as time2
from business;

time1表示上次购买时间,'1900-01-01’表示为null时的默认值,time2表示上上次购买时间,下次购买时间可用lead表达。
hive(四)函数详解1(内有窗口函数详解)_第11张图片

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

select name,orderdate,cost from (
 select name,orderdate,cost, ntile(5) over(order by orderdate) 
sorted
 from business
) t
where sorted = 1;

在这里插入图片描述

ntile(5)是指分成5个组

1.7 Rank

1.函数说明
RANK() 排序相同时会重复,总数不会变
DENSE_RANK() 排序相同时会重复,总数会减少
ROW_NUMBER() 会根据顺序计算
2.数据准备

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

3.需求
计算每门学科成绩排名。
4.创建本地 score.txt,导入数据

[liuyongjun@hadoop102 data]$ vim score.txt

hive(四)函数详解1(内有窗口函数详解)_第12张图片

5.创建 hive 表并导入数据

create table score(
name string,
subject string, 
score int) 
row format delimited fields terminated by "\t";
load data local inpath '/opt/module/data/score.txt' into table score;

6.按需求查询数据

select name,
subject,
score,
rank() over(partition by subject order by score desc) rp,
dense_rank() over(partition by subject order by score desc) drp,
row_number() over(partition by subject order by score desc) rmp
from score;

hive(四)函数详解1(内有窗口函数详解)_第13张图片

2.课堂练习

2.1 案例一

1.数据准备

u01	2017/1/21	5
u02	2017/1/23	6
u03	2017/1/22	8
u04	2017/1/20	3
u01	2017/1/23	6
u01	2017/2/21	8
u02	2017/1/23	6
u01	2017/2/22	4

2.需求
要求使用SQL统计出每个用户的累积访问次数,具体如下:

用户id	月份	小计	累积
u01	2017-01	11	11
u01	2017-02	12	23
u02	2017-01	12	12
u03	2017-01	8	8
u04	2017-01	3	3

3.创建表并导入数据

create table visit
 (userId string,
  visitDate string,
  visitCount int)
  row format delimited fields terminated by '\t';
load data local inpath '/opt/module/data/visit.txt' into table visit;

4.操作
逐步实现:
第一步:

select 
 userId,
 date_format(regexp_replace(visitDate,'/','-'),'yyyy-MM') visitDate,
 visitCount
from 
 visit;

hive(四)函数详解1(内有窗口函数详解)_第14张图片
第二步:在上一步嵌套

select 
 userId,
 visitDate,
 sum(visitCount)
from 
 (select 
 userId,
 date_format(regexp_replace(visitDate,'/','-'),'yyyy-MM') visitDate,
 visitCount
from 
 visit)t1
group by 
 userId,visitDate;

在这里插入图片描述

第三步继续嵌套

select 
 userId,
 visitDate,
 sum_visitCount,
 sum(sum_visitCount) over(partition by userId order by visitDate)
from
 (select 
 userId,
 visitDate,
 sum(visitCount) sum_visitCount
from 
 (select 
 userId,
 date_format(regexp_replace(visitDate,'/','-'),'yyyy-MM') visitDate,
 visitCount
from 
 visit)t1
group by 
 userId,visitDate)t2;

hive(四)函数详解1(内有窗口函数详解)_第15张图片

2.2 案例二

有若干个京东店铺,每个顾客访问任何一个店铺的任何一个商品时都会产生一条访问日志,访问日志存储的表名为visit,访客的用户id为user_id,被访问的店铺名称为shop,

1.简单数据:

u1	a
u2	b
u1	b
u1	a
u3	c
u4	b
u1	a
u2	c
u5	b
u4	b
u6	c
u2	c
u1	b
u2	a
u2	a
u3	a
u5	a
u5	a
u5	a

2.建表:

create table visit1(user_id string,shop string) row format delimited fields terminated by '\t';
load data local inpath '/opt/module/data/visit1.txt' into table visit1;

3.需求
1)每个店铺的UV(访客数)
2)每个店铺访问次数top3的访客信息。输出店铺名称、访客id、访问次数
4.操作
1)每个店铺的UV(访客数)
第一步:去重

select
 shop,
 user_id
from
 visit1
group by 
 shop,user_id;

hive(四)函数详解1(内有窗口函数详解)_第16张图片

第二步:计数

select 
 shop,
 count(*) uv
from
 (select
 shop,
 user_id
from
 visit1
group by 
 shop,user_id)t1
group by
 shop; 

在这里插入图片描述
2)每个店铺访问次数top3的访客信息。输出店铺名称、访客id、访问次数
第一步:计算每个人访问每个店铺的总次数

select 
 shop,
 user_id,
 count(*)
from 
 visit1
group by
 shop,user_id; 

hive(四)函数详解1(内有窗口函数详解)_第17张图片
第二步:针对同一店铺,对访问次数进行逆序排序,并添加rank值

select 
 shop,
 user_id,
 ct,
 row_number() over(partition by shop order by ct desc) rk
from 
 (select 
 shop,
 user_id,
 count(*) ct
from 
 visit1
group by
 shop,user_id)t1;

hive(四)函数详解1(内有窗口函数详解)_第18张图片
第三步:再进行子查询,取店铺访问次数前三用户信息

select 
 shop,
 user_id,
 ct
from 
 (select 
 shop,
 user_id,
 ct,
 row_number() over(partition by shop order by ct desc) rk
from 
 (select 
 shop,
 user_id,
 count(*) ct
from 
 visit1
group by
 shop,user_id)t1)t2
where rk <=3;

hive(四)函数详解1(内有窗口函数详解)_第19张图片

你可能感兴趣的:(Bigdata,#,hive)