HQL(Hive SQL) 之查询语句专题汇总

hql 同时被 3 个专栏收录
5 篇文章 0 订阅
19 篇文章 0 订阅
9 篇文章 0 订阅

HQL(Hive SQL) 之查询语句专题汇总

1. 背景

  1. hive本身是一个将sql语句转换为mapreduce 程序运行的转换器
  2. hive可以把结构化数据转换到一张表上,并提供查询和分析的功能
  3. 针对这个过程,hive从sql优化、从mapreduce优化这2个大的角度来提升hive的性能表现。
  4. sql优化,这个基于现有的第三方组件是比较成熟的技术解决方案。但优化mapreduce则需要更多精力。因为mapreduce代码是根据模板,将sql经过这个模板,转换为mapreduce程序。
  5. hive本身是一个数据仓库工具,所以大部分场景都是数据一次插入或者导入,多次查询和分析,再导出。
  6. 所以数据查询是hive的重中之重!!!!

2. 基本查询语句

[WITH CommonTableExpression (, CommonTableExpression)*] (Note: Only available
starting with Hive 0.13.0)
SELECT [ALL | DISTINCT] select_expr, select_expr, …
FROM table_reference
[WHERE where_condition]
[GROUP BY col_list]
[ORDER BY col_list]
[CLUSTER BY col_list
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number]

2.1 全表和特定列查询

  1. 全表查询(考虑到性能,不管是传统数据库还是HQL场景,都需要尽力避免使用全表查询)
select * from tb_test;
  1. 选择特定列查询
# 一般为了性能,都会选择所需要字段进行查询,尽力尽力避免全表查询,特别HQL属于海量数据处理,全表查询会给集群带来巨大压力,耗时也会很久
select age, name from tb_test;

2.2 列别名

别名可以看作是一个简称,类似于C语言中的宏定义,可以将一个字段名、查询结果集都是用别名代称。
但需要注意,别名的定义要在使用前,所以需要注意sql语句的执行顺序

select
xxxx,yyyy
from
where
group by
having
limit
整体是先执行from,然后是where,然后是查询字段,然后是group by,having,limit。所以如果需要使用别名但不确定的话,先确定sql执行顺序。
使用嵌套子查询时,hql中使用括号包起来的部分请一定一定带上别名,否则会出错

2.3算数运算符

  1. A+B A和B 相加
  2. A-B A减去B
  3. A*B A和B 相乘
  4. A/B A除以B
  5. A%B A对B取余
  6. A&B A和B按位取与
  7. A|B A和B按位取或
  8. A^B A和B按位取异或
  9. ~A A按位取反
select age+1 from tb_person;

2.4常用函数

  1. 求行数
select count(*) as cnt from tb_person;

# count(1)比count(*)要快,如果要对字段计数,内部加distinct时谨慎,这样会比较耗时,建议改为分组后再count(1)
select count(1) as cnt from tb_person;
  1. 求最大值
select max(age) as age_max from tb_person;
  1. 求最小值
select min(age) from tb_person;
  1. 求总和
select sum(salary) as total_salary from tb_person;
  1. 求平均值
select avg(age) as age_average from tb_person;

注意,如果查询结果需要用到聚合函数,进行嵌套子查询时,一般都是在最后一层时再计算,这样可以有比较清晰的查询逻辑

2.5 limit语句

主要用于限制返回结果条数(行数)

# 返回10条
select * from tb_test limit 10;

# 第一个数字0,是指起始行数,一般从0行开始计算,第二个是返回的行数。大家在网页和app看到的分页加载就是使用limit来进行数据切割并返回的,而且大部分一页数据是10或者15条。
select * from tb_test limit 9, 10;

3. where语句

where的用法和正常的sql规范用法一致,属于限定条件,同时having也是一样,可以针对group by之后数据继续限定

  1. 限定
select age, name from tb_person where age > 23;
  1. 比较运算符,当出现限定时,则必然需要有比较条件来判断是否符合条件。这些运算符可以出现在join on和having中,join on之后跟字段匹配,但需要注意避免笛卡尔积出现。having则是分组后进一步限定。
  1. A=B 基本数据类型 如果A等于B则返回TRUE,反之返回FALSE
  2. A<=>B 基本数据类型 如果A和B都为NULL,则返回TRUE,其他的和等号(=)操作符的结果一致,如果任一为NULL则结果为NULL
  3. A<>B, A!=B 基本数据类型 A或者B为NULL则返回NULL;如果A不等于B,则返回TRUE,反之返回FALSE
  4. A<B 基本数据类型 A或者B为NULL,则返回NULL;如果A小于B,则返回TRUE,反之返回FALSE
  5. A<=B 基本数据类型 A或者B为NULL,则返回NULL;如果A小于等于B,则返回TRUE,反之返回FALSE
  6. A>B 基本数据类型 A或者B为NULL,则返回NULL;如果A大于B,则返回TRUE,反之返回FALSE
  7. A>=B 基本数据类型 A或者B为NULL,则返回NULL;如果A大于等于B,则返回TRUE,反之返回FALSE
  8. A [NOT] BETWEEN B AND C 基本数据类型 如果A,B或者C任一为NULL,则结果为NULL。如果A的值大于等于B而且小于或等于C,则结果为TRUE,反之为FALSE。如果使用NOT关键字则可达到相反的效果。
  9. A IS NULL 所有数据类型 如果A等于NULL,则返回TRUE,反之返回FALSE
  10. A IS NOT NULL 所有数据类型 如果A不等于NULL,则返回TRUE,反之返回FALSE
  11. IN(数值1, 数值2) 所有数据类型 使用 IN运算显示列表中的值
  12. A [NOT] LIKE B STRING 类型 B是一个SQL下的简单正则表达式,如果A与其匹配的话,则返回TRUE;反之返回FALSE。B的表达式说明如下:‘x%’表示A必须以字母‘x’开头,‘%x’表示A必须以字母’x’结尾,而‘%x%’表示A包含有字母’x’,可以位于开头,结尾或者字符串中间。如果使用NOT关键字则可达到相反的效果。
  13. A RLIKE B, A REGEXP B STRING 类型 B是一个正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是JDK中的正则表达式接口实现的,因为正则也依据其中的规则。例如,正则表达式必须和整个字符串A相匹配,而不是只需与其字符串匹配。

官方文档:https://cwiki.apache.org/confluence/display/Hive/LanguageManual+UDF
在这里插入图片描述

select * from emp where sal =5000;

select * from emp where sal between 500 and 1000;

select * from emp where comm is null;

select * from emp where sal IN (1500, 5000);
  1. like、rlike
    在进行条件过滤时,如果涉及到字符串的匹配和判断,则需要like和rlike正则判断。
    实际生产中,对于字符串的处理其实占据了相当部分的比例,所以如果可能,对于正则表达式还是可以花时间研究一下的。
  • 使用like选择类似的值
  • 选择条件中,可以使用 % 代表0或者多个字符
  • 使用 _ 代表一个字符
  • rlike就是regex like的意思,可以跟随一个java的正则表达式。注意正则表达式其实也是一套规范,不同编程语言中的正则表达式细节上是会有差异的。
select * from emp where sal LIKE '2%';

select * from emp where sal LIKE '_2%';

 select * from emp where sal RLIKE '[2]';

  1. 逻辑运算符
  1. AND 逻辑并
  2. OR 逻辑或
  3. NOT 逻辑否
    注意拼接join是,on不能跟or,hive中on不支持不等连接,也就是一般都是x join y on x.id=y.id
select * from emp where sal>1000 and deptno=30;

select * from emp where sal>1000 or deptno=30;

select * from emp where deptno not IN(30, 20);

4. 分组

  1. group by, 可以传入单个或者多个字段进行分组。
    注意使用group by的时候,如果需要访问分组前数据,使用开窗函数会更加合适(聚合函数之后,加上over(),再在over中进行条件设定,如partion by order by limit等)
  2. group by一般和聚合函数一起使用,对结果分组后,对每个组进行聚合操作
# 注意这里的字段访问,只能直接访问分组的字段t.deptno。其他都是通过聚合函数avg()进行访问和处理的
select t.deptno, avg(t.sal) avg_sal from emp t group by t.deptno;

select t.deptno, t.job, max(t.sal) max_sal from emp t group by
t.deptno, t.job;
  1. having限定词
  • having是对where的补充,where是针对表中列进行限定,having则是针对查询结果的列进行限定
  • where后面是不能写分组函数,但having后可以跟分组函数
  • having只用于group by分组统计语句
select deptno, avg(sal) from emp group by deptno;

# 注意这里别名avg_sal 的定义,由于查询字段执行要比having更早,所以having可以使用这个别名
select deptno, avg(sal) avg_sal from emp group by deptno having
avg_sal > 2000;

5.join语句

  1. join其实就是代表着生产中常见一个场景,多表查询,也叫做联表查询。这个表可能是查询的一个中间子集,可能是一张实际存在的表,一般联表2–3张,甚至更多都有。
  2. 常见的 x join y on x.xid=y.yid

5.1 等值join

emp join dept on emp.dptno=dept.dptno

hive支持join,在旧版本不支持不等值join,新版本3.1.2中是支持不等值join的。也就是在on那里,可以把=换成!=或者其他限定条件

5.2 表的别名在join时使用

由于join多张表时,sql语句可能会非常长,使用别名来替代一串sql语句或者字段是非常有利于sql语句的阅读和维护使用的。
而且,如果使用表名前缀可以提高执行效率

select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno = d.deptno;

在这里插入图片描述

5.3 内连接

2个连接的表中都存在与连接条件匹配的数据,这些数据才会被保留下来

# 注意,使用别名时,最好使用as来显示标识出这是别名,算是一种好的编码习惯
# 过长的sql语句可以换行显示,这样看起来可能会更有利于阅读一些
select 
e.empno, 
e.ename, 
d.deptno 
from 
emp as e 
join dept as d 
on 
e.deptno = d.deptno;

5.4 左外连接

join左边表符合where子句所有数据被返回,也就是以左边为主

 select 
 e.empno, 
 e.ename, 
 d.deptno 
 from emp as e 
 left join 
 dept as d 
 on e.deptno = d.deptno;

5.5 右外连接

join右侧符合where条件的所有数据都会返回,也就是以右侧数据为主

select 
e.empno, 
e.ename, 
d.deptno 
from emp as e 
right join 
dept as d 
on e.deptno = d.deptno;

5.6满外连接

将返回join左右2侧表中,所有符合where条件的数据。没有则使用null代替

select 
e.empno, 
e.ename, 
d.deptno 
from 
emp as e 
full join 
dept as d 
on 
e.deptno = d.deptno;

5.7 多表连接

SELECT 
e.ename, 
d.deptno, 
l.loc_name
FROM   
emp as e 
JOIN   
dept as d
ON     
d.deptno = e.deptno 
JOIN   
location as l
ON     
d.loc = l.loc;

hive内部机制,一般一个join对象启动一个mapreduce任务,所以本案例中会有2个mapreduce任务。注意这里的执行顺序也是先 e 和 d ,然后是这个结果再和 l 进行处理。

5.8 笛卡尔积

  1. 笛卡尔积可以理解为2个集合中数据注意交叉运算,这样会导致数据量暴增。除非其中一张是很小的表,否则2张达标一旦发生笛卡尔积,会导致结果集中数据量是2张大表结果之积,也就是相乘的结果。
  2. 一般在join是on的条件失效
  3. 一般在join是忽略on条件
  4. 所有表中的行互相连接
select 
empno, 
dname 
from 
emp, 
dept;

注意,使用查询时,需要i尽力避免笛卡尔积产生,除非能够确认其中一张表是小表,否则数据量会暴增。

5.9 join连接词中不支持or

select e.empno, e.ename, d.deptno from emp e join dept d on e.deptno
= d.deptno or e.ename=d.ename;   错误的

6. 排序

在做实际数据处理时,经常需要对数据进行排序,最多的,最高的,最少的等等,这时候就需要处理几个问题:
如何排序
根据什么排序
如何提升排序速度进而加快查询速度

6.1 全局排序

  1. order by,注意这个排序是对整体排序,比较消耗时间。
  2. 排序顺序,asc,这是默认的,desc降序,需要设置。
  3. 排序不管是数字还是字符串,都可以排序。字符串就是自然字母升序排序
# 默认就是asc升序,所以不需要单独设置
select * from emp order by sal;

select * from emp order by sal desc;

6.2 按照别名排序

# 使用别名有一个前提,就是别名需要先执行,从此前sql语句的执行顺序可知字段查询只排在from之后,所以order by的时候是可以使用的。
select 
ename, 
sal*2  as twosal 
from 
emp 
order by twosal;

6.3 多个列排序

# 多个字段排序,就和现实中排序一样,先按照第一个标准排序,排完之后再按照第二个标准排序。
select 
ename, 
deptno, 
sal 
from 
emp 
order by deptno, sal ;

6.4 每个mapreduce内部排序(sort by)

  1. 本质就是reducer中进行排序
  2. 所以sort by结合distribute by使用时,distribute by在map阶段对key进行分组,sort by对分组后的数据在reduce 阶段排序
  3. 所以reducer中排序,但整个结果集合来说并不算排序
  • 设置reduce个数
set mapreduce.job.reduces=3;
  • 查看设置的reduce任务个数
set mapreduce.job.reduces;
  • 根据部门编号降序查看员工信息
select 
* 
from 
emp 
sort by 
empno desc;
  • 将结果导入到文件中,按照部门编号降序排列
insert overwrite local directory '/hive/sortby_result'
 select * from emp sort by deptno desc;

6.5 分区排序 distribute by(分区字段)

  1. 分区排序,类似mapreduce中的partition,进行分区,一般集合sort by使用。
  2. hive规范,distribute by写在sort by之前。
  3. 对于distribute by的使用,一般分配多reduce进行处理,否则效果可能不会很明显。
set mapreduce.job.reduces=3;
insert overwrite local directory '/root/data/distribute-result' 
select 
* 
from 
emp 
distribute by deptno 
sort by empno desc;

6.6 cluster by排序

  1. 当distribute by和sort by字段相同时,可以使用cluster by进行替代。
  2. 本质就是查询数据时,对根据字段名进行map数据分区,然后reduce阶段再进行排序处理
  3. 不过cluster只能升序,不能降序,所以灵活使用的话,还是distribute by结合sort by更灵活一些。
  4. 注意,例如按照部门编号划分,并不是20号部门和30号部门就区分开,而是有可能在一个区中。
select * from emp cluster by deptno;


 select * from emp distribute by deptno sort by deptno;

在这里插入图片描述

7. 分桶及抽样查询

  1. 在处理海量数据时,如何更有效进行查询。
  2. 如果数据有明显的数据特征,则可以进行分区管理,如日志文件,可以按照年、月、日进行分区管理,这样查询数据时,可以直接使用where指定对应的区,这样hdfs文件查找直接找到对应文件夹
  3. 如果数据需要进行join操作,则可以根据一定规则对数据做粪桶操作,简单如根据字段的hashcode进行分桶,和mapreduce 的shuffle分区一样。这样字段进行on检索匹配时,会有更高的效率,因为可以直接去对应桶中进行数据join字段匹配。

7.1 分桶表数据存储

概述
  1. hive分桶可以按照分桶键的哈希值进行划分,分到不同文件中去,这些小文件称之为桶。
  2. 分区针对的是数据的存储路径,分桶针对的是数据文件
  3. 分区提供一个隔离数据和优化查询的便利方式。但不是所有数据集都能形成合理的分区,需要确定合适的划分大小。
  4. 分桶是将数据集分解为更合适管理的若干部分的另一个技术。桶上可以加额外结构,链接相同列划分了桶的表,可以使用map side join技术,更高效。取样sampling更加高效,没有分区则需要扫描整个数据集合
代码
  • 分桶表
# 注意这里和分区不一样,分桶是按照
create table buck_demo(
id int, 
name string
)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\t';
  • 查看表结构
desc formatted buck_demo;
  • 创建普通表
create table stu(id int, name string)
row format delimited fields terminated by '\t';
  • 普通表中加载数据
load data local inpath '/data/student.txt' into table stu;
  • 设置属性
set hive.enforce.bucketing=true;     -- 开启分桶
set mapreduce.job.reduces=-1;         --  默认reduce个数
  • 将查询的数据导入到分桶表中
insert into table buck_demo
select id, name from stu;

7.2 分桶抽样查询

  1. 当查询时,不需要一个准确数据,需要一个概略数据时,抽样就起到作用。特别是针对海量数据,有时候要求处理到每一条数据是不现实甚至是不可能的。
  2. 抽样关键就是如何保证随机性,保证抽样出来的数据分布和整体相对一致
# 就是把数据分成四份,注意不是均等划分,有的可能为空,取其中一份的数据。因为整体是随机划分的,所以可以保证随机性。
 select 
 * 
from  
buck_demo 
tablesample(bucket 1 out of 4 on id);
  1. TABLESAMPLE(BUCKET x OUT OF y)

y必须是table总bucket数的倍数或者因子。
hive根据y的大小,决定抽样的比例。
例如,table总共分了4份,当y=2时,抽取(4/2=)2个bucket的数据,当y=8时,抽取(4/8=)1/2个bucket的数据。

x表示从哪个bucket开始抽取,如果需要取多个分区,以后的分区号为当前分区号加上y。
例如,table总bucket数为4,tablesample(bucket 1 out of 2),表示总共抽取(4/2=)2个bucket的数据,抽取第1(x)个和第3(x+y)个bucket的数据。
注意:x的值必须小于等于y的值,否则出错

8. 常用查询函数

8.1 空字段赋值

nvl
NVL( string1, replace_with)

它的功能是如果string1为NULL,则NVL函数返回replace_with的值,否则返回string1的值
如果两个参数都为NULL ,则返回NULL。
在这里插入图片描述

8.2 case when

相当于java 的 switch case 或者if else

案例

  1. 数据准备
悟空	A	男
娜娜	A	男
宋宋	B	男
凤姐	A	女
热巴	B	女
慧慧	B	女
  1. 需求
    求出不同部门男女各多少人。结果如下:
A     2       1
B     1       2
  1. 创建文本文件,导入数据
vi emp_sex.txt
  1. 创建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/datas/emp_sex.txt' into table emp_sex;
  1. 按照需求查询数据
select 
dept_id,
sum(case sex when '男' then 1 else 0 end) as male_count,
sum(case sex when '女' then 1 else 0 end) as female_count
from 
emp_sex
group by
dept_id;

8.3 行转列

概述

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

案例:

  1. 数据
孙悟空	白羊座	A
娜娜	     射手座	A
宋宋	     白羊座	B
猪八戒    白羊座	A
凤姐	     射手座	A
  1. 需求
    把星座和血型一样的人归类到一起。结果如下:
射手座,A            娜娜|凤姐
白羊座,A            孙悟空|猪八戒
白羊座,B            宋宋
  1. 创建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/datas/person_info.txt” into table person_info;
  1. 检索数据
# 注意hql中一旦使用括号括起来,就需要使用别名,否则会出错
select
t1.base,
concat_ws('|', collect_set(t1.name)) as name
from
(select
 name,
 concat(constellation, ",", blood_type) as base
 from
 person_info) as t1
group by
t1.base;

8.4 列转行

概述

  1. explode
    EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。 [爆炸, 炸裂]
  2. lateral view(和plit、explode结合使用,效果更强大). 生成一个结果集合
  • 一入多出
  • 用法:LATERAL VIEW udtf(expression) table Alias AS columnAlias
  • 解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

案例:

  1. 数据
《疑犯追踪》	悬疑,动作,科幻,剧情
《Lie to me》	悬疑,警匪,动作,心理,剧情
《战狼2》	战争,动作,灾难
  1. 需求
    将电影分类中的数组数据展开。结果如下:
《疑犯追踪》      悬疑
《疑犯追踪》      动作
《疑犯追踪》      科幻
《疑犯追踪》      剧情
《Lie to me》   悬疑
《Lie to me》   警匪
《Lie to me》   动作
《Lie to me》   心理
《Lie to me》   剧情
《战狼2》        战争
《战狼2》        动作
《战狼2》        灾难
  1. 创建hive表
create table movie(
    name string, 
    category array<string>
    ) 
row format delimited fields terminated by "\t"
collection items terminated by ",";

load data local inpath "/opt/module/datas/movie.txt" into table movie_info;
  1. 检索数据
select
    movie,
    category_name
from 
    movie_info lateral view explode(category) table_tmp as category_name;

8.5 窗口函数

概述

当分组聚合之后,还想操作集合之前的数据,就需要使用窗口函数。

  1. over(), 指定分析函数工作的数据窗口大小,这个窗口大小会随着行的变化而变化
  1. CURRENT ROW:当前行 current row
  2. n PRECEDING:往前n行数据 n preceding
  3. n FOLLOWING:往后n行数据 n following
  4. UNBOUNDED:起点,UNBOUNDED PRECEDING 表示从前面的起点, UNBOUNDED FOLLOWING表示到后面的终点 unbound preceding unbound following
  5. LAG(col,n):往前第n行数据 lag 参数一 字段 n
  6. LEAD(col,n):往后第n行数据 lead
  7. NTILE(n):把有序分区中的行分发到指定数据的组中,各个组有编号,编号从1开始,对于每一行,NTILE返回此行所属的组的编号。注意:n必须为int类型。 ntile(5)
    Divides an ordered partition into x groups called buckets and assigns a bucket number to each row in the partition. This allows easy calculation of tertiles, quartiles, deciles, percentiles and other common summary statistics. (As of Hive 0.11.0.)

案例

  1. 数据准备
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. 需求

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

  1. 创建hive表并导入数据
create table business(
name string, 
orderdate string,
cost int
) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',';

load data local inpath "/root/hive_sql/window4.txt" into table business;

在这里插入图片描述
4. 按照需求查询

  • (1)查询在2017年4月份购买过的顾客及总人数
select 
name,
count(*) over () 
from 
business
where substring(orderdate, 1, 7) = '2017-04' 
group by name;

在这里插入图片描述

  • (2)查询顾客的购买明细及月购买总额
select 
name,
orderdate,
cost,
sum(cost) over(partition by month(orderdate)) 
from
business;

在这里插入图片描述

  • (3)上述的场景,要将cost按照日期进行累加
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;

在这里插入图片描述

  • (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;

在这里插入图片描述

  • (5)查询前20%时间的订单信息
select 
*
from
(
select
* ,
ntile(5) over(order by orderdate ) as n
from
business
) as t
where t.n = 1;

在这里插入图片描述

8.6 rank

  1. rank() 排序相同时,会重复,总数不变
  2. dense_rank() 排序相同时会重复,总数会减少
  3. row_number() 会根据顺序计算

案例

  1. 数据
孙悟空	语文	87
孙悟空	数学	95
孙悟空	英语	68
娜娜	语文	94
娜娜	数学	56
娜娜	英语	84
宋宋	语文	64
宋宋	数学	86
宋宋	英语	84
婷婷	语文	65
婷婷	数学	85
婷婷	英语	78
  1. 需求
    计算每门学科成绩排名
  2. 创建本地文件
    /root/hive_sql/rank_src.txt
  3. 创建hive表并导入
create table tb_score(
name string,
subject string,
score int
)
row format delimited fields terminated by '\t';


load data local inpath '/root/hive_sql/rank_src.txt' into table tb_score;

在这里插入图片描述

  1. 按照需求查询
select
name,
 subject,
 score,
 rank() over(partition by subject order by score desc) as rk,
 dense_rank() over(partition by subject order by score desc) as dense_rk,
 row_number() over(partition by subject order by score desc) as rn
from 
tb_score;

在这里插入图片描述
从结果可以看出,只有row number是按照顺序往下计数,rank则排序相同时会减少一个序号,但总数不会改百年,dense rank则会总数都会减少

8.7 if

if(boolean testCondition, T valueTrue, T valueFalseOrNull)
就是hql中的判断语句,和case when很像,适合判断一个条件时

返回值: T
说明: 当条件testCondition为TRUE时,返回valueTrue;否则返回valueFalseOrNull
在这里插入图片描述

案例

  1. 数据
a,2017-02-05,200
a,2017-02-06,300
a,2017-02-07,200
a,2017-02-08,400
a,2017-02-10,600
b,2017-02-05,200
b,2017-02-06,300
b,2017-02-08,200
b,2017-02-09,400
b,2017-02-10,600
c,2017-01-31,200
c,2017-02-01,300
c,2017-02-02,200
c,2017-02-03,400
c,2017-02-10,600
a,2017-03-01,200
a,2017-03-02,300
a,2017-03-03,200
a,2017-03-04,400
a,2017-03-05,600
  1. 需求
    连续3天以上销售记录的店铺名称
    (连续七天登录的用户等等)
  2. 建立hive表格,并导入数据
create table tb_shopping_log(
name string,
cday string,
cost int
)
row format delimited fields terminated by ',';

load data local  inpath '/root/hive_sql/hive_window4.txt' into table tb_shopping_log;

在这里插入图片描述

  1. hql查询数据
select
name,
cday,
cost,
row_number() over(partition by name order by cday) as rn
from
tb_shopping_log;

在这里插入图片描述

select
name,
cday,
cost,
date_sub(cday, rn) as datesub
from
(select
name,
cday,
cost,
row_number() over(partition by name order by cday) as rn
from
tb_shopping_log) as t;

在这里插入图片描述

select
name,
count(1) as count
from
(select
name,
cday,
cost,
date_sub(cday, rn) as datesub
from
(select
name,
cday,
cost,
row_number() over(partition by name order by cday) as rn
from
tb_shopping_log) as t) as t2
group by datesub, name
having count > 3;

在这里插入图片描述
如果需要去重,再嵌套一层子查询,使用distinct即可。这个可以自行尝试,算是留的一个小谜底。

  • 4
    点赞
  • 2
    评论
  • 14
    收藏
  • 打赏
    打赏
  • 扫一扫,分享海报

评论 2 您还未登录,请先 登录 后发表或查看评论
©️2022 CSDN 皮肤主题:深蓝海洋 设计师:CSDN官方博客 返回首页

打赏作者

闻香识代码

你的鼓励将是我创作的最大动力

¥2 ¥4 ¥6 ¥10 ¥20
输入1-500的整数
余额支付 (余额:-- )
扫码支付
扫码支付:¥2
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、C币套餐、付费专栏及课程。

余额充值