大数据开发之Hive(查询、分区表和分桶表、函数)

第 6 章:查询

6.1 基本语法及执行顺序

1、查询语句语法

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、书写次序和执行次序

顺序书写次序书写次序说明执行次序执行次序说明
1select查询from先执行表与表直接的关系
2from先执行表与表直接的关系on先执行表与表直接的关系
3join on先执行表与表直接的关系join先执行表与表直接的关系
4where先执行表与表直接的关系where过滤
5group by分组group by分组
6having分组后再过滤having分组后再过滤
7distribute by cluster by4个byselect查询
8sort by4个bydistinct去重
9order by4个bydistribute by cluster by4个by
10limit限制输出的行数sort by4个by
11union/union all合并order by4个by
12limit限制输出的行数
13union/union all合并

6.2 基本查询(Select…From)

6.2.1 全表和特定列查询

1、数据准备
分别创建部门和员工外部表,并向表中导入数据。
1)在/opt/module/hive/datas目录下编辑文件dept.txt,添加如下内容。

 vim dept.txt
10	行政部	1700
20	财务部	1800
30	教学部	1900
40	销售部	1700

2)在/opt/module/hive/datas目录下编辑文件emp.txt,添加如下内容。

vim emp.txt
7369	张三	研发	800.00	30
7499	李四	财务	1600.00	20
7521	王五	行政	1250.00	10
7566	赵六	销售	2975.00	40
7654	侯七	研发	1250.00	30
7698	马八	研发	2850.00	30
7782	金九	\N	2450.0	30
7788	银十	行政	3000.00	10
7839	小芳	销售	5000.00	40
7844	小明	销售	1500.00	40
7876	小李	行政	1100.00	10
7900	小元	讲师	950.00	30
7902	小海	行政	3000.00	10
7934	小红明	讲师	1300.00	30

3)上传数据到HDFS

dfs -mkdir /user/hive/warehouse/dept;
dfs -mkdir /user/hive/warehouse/emp;
dfs -put /opt/module/hive/datas/dept.txt /user/hive/warehouse/dept;
dfs -put /opt/module/hive/datas/emp.txt /user/hive/warehouse/emp;

4)建表语句,创建外部表
创建部门表dept

create external table if not exists dept(
deptno int,--部门编号
dname string, --部门名称
loc int --部门位置
)
row format delimited
fields terminated by '\t';

创建员工表

create external table if not exists emp(
empno int, --员工编号
ename string, --员工姓名
job string, --员工岗位(大数据工程师、前端工程师、java工程师)
sal double,--员工薪资
deptno int --部门编号
)
row format delimited fields terminated by '\t';

2、全表查询

select * from EMP;
select empno,ename,job,mgr,hiredate,sal,comm,deptno from emp ;

3、选定特定列查询

select empno, ename from emp;

注意:
1、SQL语言大小写不敏感
2、SQL可以写在一行或者多行
3、关键字不能被缩写也不能分行
4、各子句一般要分行写
5、使用缩进提高语句的可读性

6.2.2 列别名

紧跟列名,也可以在列名和别名之间加入关键字‘AS’
如:

select ename AS name,deptno dn 
from emp;

6.2.3 常用函数(set hive.exec.mode.local.auto=true;本地模式)

1、求emp表的总行数(count)

select count(*) cnt from emp;

2、求emp表中工资的最大值

elect max(sal) max_sal from emp;

3、求emp表中工资的最小值

elect min(sal) min_sal from emp;

4、求emp表中工资的总和

elect sum(sal) sum_sal from emp;

5、求emp表中工资的平均值

select avg(sal) avg_sal from emp;

6.2.4 Limit语句

一般的查询会返回多行数据,在生产环境中,通常使用LIMIT子句用于限制返回的行数

select ename, sal from emp limit 5;
select ename, sal from emp limit 2,3;

6.2.5 Where语句

1、实例:查询出薪水大于1000的所有员工

select * from emp where sal > 1000;

6.2.6 比较运算符(Between/In/Is Null)

1、下面表中描述了谓词操作符,这些操作符同样可以用于JOIN…ON和HAVING语句中。

操作符支持的数据类型描述
A<=>B基本数据类型如果A和B都为NULL,则返回TRUE,如果以便为NULL,返回False
A RLIKE BSTRING类型B是基于java的正则表达式,如果A与其匹配,则返回TRUE;反之返回FALSE。匹配使用的是

2、案例实操
1)查询出薪水等于5000的所有员工

select * from emp where sal =5000;
OK
emp.empno       emp.ename       emp.job emp.mgr emp.hiredate    emp.sal emp.comm        emp.deptno
7839    KING    PRESIDENT       NULL    1981-11-17      5000.0  NULL    10

2)查询工资在500到1000的员工信息

select * from emp where sal between 800 and 1100;
OK
emp.empno       emp.ename       emp.job emp.mgr emp.hiredate    emp.sal emp.comm        emp.deptno
7369    SMITH   CLERK   7902    1980-12-17      800.0   NULL    20
7876    ADAMS   CLERK   7788    1987-5-23       1100.0  NULL    20
7900    JAMES   CLERK   7698    1981-12-3       950.0   NULL    30

3)查询job为空的所有员工信息

select * from emp where job is null;
OK
emp.empno       emp.ename       emp.job emp.mgr emp.hiredate    emp.sal emp.comm        emp.deptno
7369    SMITH   CLERK   7902    1980-12-17      800.0   NULL    20
7566    JONES   MANAGER 7839    1981-4-2        2975.0  NULL    20
7698    BLAKE   MANAGER 7839    1981-5-1        2850.0  NULL    30

4)查询工资是1500或5000的员工信息

select * from emp where sal IN (1500, 5000);
OK
emp.empno       emp.ename       emp.job emp.mgr emp.hiredate    emp.sal emp.comm        emp.deptno
7839    KING    PRESIDENT       NULL    1981-11-17      5000.0  NULL    10
7844    TURNER  SALESMAN        7698    1981-9-8        1500.0  0.0     30

6.2.8 Like 和 RLike

1、like关键字:使用LIKE运算选择类似的值
2、选择条件可以包含字符或数字:
1)% -> 代表零个或多个字符
2)_ -> 代表一个字符
3、RLIKE关键字:RLIKE子句是Hive中这个功能的一个扩展,其可以通过java的正则表达式这个更加强大的语言来指定匹配条件。
1)$x -> 代表以x结尾
2)^x -> 代表以x开头
3).* 任意数量字符
4). 一个任意字符
5)*上一个字符可以无限次出现或者不出现
4、实例操作
1)查找名字以“小”开头的员工信息

select * from emp where ename LIKE '小%';
select * from emp where ename RLIKE '^小';

2)查找名字以“明”结尾的员工信息

select * from emp where ename LIKE '%明';
select * from emp where ename RLIKE '明$';

3)查找名字中带有“明”的员工信息

select * from emp where ename  LIKE '%明%';
select * from emp where ename  RLIKE '[明]';

6.3 排序

6.3.1 每个Reduce内部排序(Sort By)

1、Sort by:在每个Reduce内部进行排序,对全局结果集来说不是有序。sort by为每个reducer产生一个排序文件,每个Reducer内部进行排序,对全局结果来说不是排序。
2、通过命令设置reduce个数

set mapreduce.job.reduces=3;

3、案例实操:
1)根据部门编号降序查看员工信息

select * from emp sort by deptno desc;

2)将查询结果导入到文件中

insert overwrite local directory '/opt/module/hive/datas/sortby-result'
row format delimited fields terminated by '\t '
select * 
from emp 
sort by deptno desc;

6.3.2 分区(Distribute By)

1、Distribute By
在有些情况下,我们需要控制某个特定行应该在哪个reducer,通常时为了进行后续的聚集操作。distribute by可以实现。distribute by类似MR中的partition(自定义分区),进行分区,结合sort by 使用。
2、案例分析
1)先按照部门编号分区,再按照员工薪水降序排序

set mapreduce.job.reduces=3;
insert overwrite local directory '/opt/module/hive/datas/distribute-result'
row format delimited fields terminated by '\t'
selectename,empno,deptno,sal 
from emp 
distribute by deptno
sort by sal desc;

注意:

  • distribute by的分区规则是根据分区字段的hash码与reduce的个数进行模除后,余数相同的分到一起。
  • Hive要求DISTRIBUTE BY语句要写在SORT BY语句前面。

6.3.3 Cluster By

1、cluster by:
1)当distribute by和sort by字段相同时,可以使用cluster by方式。
2)cluster by除了具有distribute by的功能外还兼具sort by的功能。
2、案例:查询emp表中的员工信息,并按照部分编号分区排序。

select ename,empno,deptno,sal from emp cluster by deptno;
select ename,empno,deptno,sal from emp distribute by deptno sort by deptno;

第 7 章 分区表和分桶表

我们创建一个hive表时,此时在hdfs上就在默认路径上创建了一个以表名字命名的文件夹。Hive表中的数据在hdfs上则是对应文件夹下的所有文件。在查询表中数据时,其实就是将文件下的所有文件进行读取,在海量数据的场景下,这无疑是非常耗时的,并且在实际生产环境中,往往会进行查询过滤。
所以,如何在海量数据的场景下进行高效的查询过滤呢?

7.1 分区表

1、分区表实际上就是对应一个HDFS文件系统上的独立的文件夹。
2、该文件夹下是该分区所有的数据文件。
3、Hive中的分区就是分目录,把一个大的数据集根据业务需求分割成小的数据集。
4、在查询时通过WHERE子句中的表达式选择查询所需要的指定的分区,这样的查询效率会提高很多。

7.1.1 分区表基本操作

1、需要根据日期对日志进行管理,通过部门信息模拟
2、创建分区表语法

create table dept_partition(
deptno int, --部门编号
dname string, --部门名称
loc string --部门位置
)
partitioned by (day string)
row format delimited fields terminated by '\t';

注意:分区字段不能是表中已经存在的数据,可以将分区字段看作表的伪列。
3、数据准备
为每个分区准备数据,我们根据日期对日志进行管理,通过部门信息模拟

vim dept_20200401.log
10	行政部	1700
20	财务部	1800 
vim dept_20200402.log
30	教学部	1900
40	销售部	1700
vim dept_20200403.log
50	运营部	2000
60	人事部	1900

4、案例:
1)向dept_partition表的分区加载数据

load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table dept_partition partition(day='20200401'); 
load data local inpath '/opt/module/hive/datas/dept_20200402.log' into table dept_partition partition(day='20200402');
load data local inpath '/opt/module/hive/datas/dept_20200403.log' into table dept_partition partition(day='20200403');

注意:分区表加载数据时,必须指定分区
在这里插入图片描述
2)查询分区表中数据
单分区查询

select * from dept_partition where day='20200401';

多分区联合查询(union必走mr效率较低)

select * from dept_partition where day='20200401'unionselect * from dept_partition where day='20200402'unionselect * from dept_partition where day='20200403';
select * from dept_partition where day='20200401' orday='20200402' or day='20200403' ;			

5、增加分区
1)添加单个分区

alter table dept_partition add partition(day='20200404') ;

2)同时添加多个分区

alter table dept_partition add partition(day='20200405') partition(day='20200406');

6、删除分区
1)删除单个分区

alter table dept_partition drop partition (day='20200406');

2)同时删除多个分区

alter table dept_partition drop partition (day='20200404'), partition(day='20200405');

7、查看分区表结构

desc formatted dept_partition;
# Partition Information          
# col_name              data_type               comment             
day                   string    

7.1.2 二级分区

思考:在根据日期分区后,如果一天的日志数据量也很大,如何再将数据拆分?
1、创建二级分区表

create table dept_partition2(deptno int,dname string,loc string
)
partitioned by (day string, hour string)
row format delimited fields terminated by '\t';

2、加载数据
1)加载数据到二级分区表中

load data local inpath '/opt/module/hive/datas/dept_20200401.log' into table dept_partition2 partition(day='20200401', hour='11');

2)查找分区数据

select * from dept_partition2 where day='20200401' and hour='11';

3、让分区表和数据产生关联的三种方式
1)、方式一:上传数据后修复
(1)上传数据

 dfs -mkdir -p /user/hive/warehouse/dept_partition2/day=20200401/hour=12;dfs -put /opt/module/hive/datas/dept_20200402.log /user/hive/warehouse/dept_partition2/day=20200401/hour=12;

(2)查询数据(查询不到刚上传的数据)

select * from dept_partition2 where day='20200401' and hour='12';

(3)执行修复命令

msck repair table dept_partition2;

(4)再次查询数据

 select * from dept_partition2 where day='20200401' and hour='12';

2)方式二:上传数据后添加分区
(1)上传数据

dfs -mkdir -p /user/hive/warehouse/dept_partition2/day=20200401/hour=13;
dfs -put /opt/module/hive/datas/dept_20200403.log /user/hive/warehouse/dept_partition2/day=20200401/hour=13;

(2)执行添加分区

alter table dept_partition2 add partition(day='20200401',hour='13');

(3)查询数据

select * from dept_partition2 where day='20200401' and hour='14';

3)方式三:创建文件夹后load数据到分区
(1)创建目录

dfs -mkdir -p /user/hive/warehouse/mydb.db/dept_partition2/day=20200401/hour=14;

(2)上传数据

load data local inpath '/opt/module/hive/datas/dept_20200401.log' into tabledept_partition2 partition(day='20200401',hour='14');

(3)查询数据

select * from dept_partition2 where day='20200401' and hour='14';

7.1.3 动态分区

引言:关系型数据库中,对分区表Insert数据时候,数据库自动会根据分区字段的值,将数据插入到相应的分区中。Hive中也提供类似的操作,即动态分区(Dynamic Partition),只不过,使用Hive的动态分区,需要进行相应的配置。
1、开启动态分区参数设置
1)开启动态分区功能

set hive.exec.dynamic.partition=true;

2)设置非严格模式(动态分区的模式,默认strict,表示必须指定至少一个分区为静态分区,nonstrict模式表示允许所有的分区字段都可以使用动态分区)

set hive.exec.dynamic.partition.mode=nonstrict

3)在所有执行MR的节点上,最大一共可以创建多少个动态分区。默认1000

set hive.exec.max.dynamic.partitions=1000;

4)在每个执行MR的节点上,最大可以创建多少个动态分区
该参数需要根据实际的数据来设定。比如,源数据中包含了一年的数据,即day字段有365个值,那么该参数就需要设置成大于365,如果使用默认100,则会报错。

set hive.exec.max.dynamic.partitions.pernode=100;

5)整个MR Job中,最大可以创建多少个HDFS文件。默认100000

set hive.exec.max.created.files=100000;

6)当有空分区生成时,是否抛出异常。一般不需要设置。默认false

set hive.error.on.empty.partition=false;

2、案例
需求:将dept表中的数据按照地区(loc字段),插入到目标表dept_partition_loc的相应分区中
1)创建部门地区分区表

create table dept_partition_dynamic(id int,name string
)
partitioned by (loc int)
row format delimited fields terminated by '\t';

2)以动态分区的方式向表中插入数据

insert into table dept_partition_loc partition(loc) select deptno, dname, loc from dept;
FAILED: SemanticException [Error 10096]: Dynamic partition strict mode requires at least one static partition column. To turn this off set hive.exec.dynamic.partition.mode=nonstrictset hive.exec.dynamic.partition.mode = nonstrict;insert into table dept_partition_dynamic partition(loc) select deptno, dname, loc from dept;

3)查看目标分区表的分区情况

show partitions dept_partition;
OK
partition
loc=1700
loc=1800
loc=1900

7.2 分桶表

1、分桶表
对于一张表或分区,Hive可以进一步组织成桶,也就是更为细粒度的数据范围划分。分区针对的是数据的存储路径(细分文件夹);分桶针对的是数据文件(按规则多文件放在一起)。
2、案例:创建分桶表
1)创建分桶表

create table stu_bucket(id int, name string)
clustered by(id) 
into 4 buckets
row format delimited fields terminated by '\t';

2)查看表结构

desc formatted stu_bucket;
Num Buckets:            4     

注意:想要将表创建为4个桶,需要将hive中mapreduce.jog.reduces参数设置为>=4或设置为-1
3)导入数据到分桶表中

load data local inpath   '/opt/module/hive/datas/student.txt' into table stu_bucket;

4)查看创建的分桶表中是否分为4个桶
在这里插入图片描述
5)查询分桶的数据

select * from stu_bucket;

6)分桶规则
Hive的分桶采取对分桶字段的值进行哈希,然后除以桶的个数求余
7)分桶表操作需要注意的事项:
(1)mapreduce.job.reduces=-1,让Job自行决定需要用多少个reduce或者将reduce的个数设置为大于等于分桶表的数量。
(2)从hdfs中load数据到分桶表中,避免本地文件找不到问题
8)insert方式将数据导入分桶表

truncate table stu_bucket;(删除表内数据,不删表结构,因此只能删内表)
insert into table stu_bucket select * from student ;

第 8 章:函数

8.1 系统内置函数

1)查看系统自带的函数

show functions;

2)显示自带的函数的用法

desc function abs;

3)详细显示自带函数的用法

desc function extended abs;

8.2 常用内置函数

8.2.1 空字段赋值-NVL(防止空字段参与计算)

1、函数说明

desc function extended nvl;

2、解释

NVL给值为NULL的数据赋值,它的格式是NVL(value,default_value)
功能如果value为NULL,则NVL函数返回default_value的值,否则返回value的值。如果两个参数都为NULL,则返回NULL

3、案例
1、数据准备
采用员工表
2、查询
1)如果员工的comm为NULL,则用0代替

select ename,comm,nvl(comm, 0) comm_0 from emp;

2)如果员工的job为NULL,则用领导id代替

select ename, mgr,comm, nvl(job,mgr) comm_mgr from emp;

8.2.2 CASE WHEN ELSE END

1、案例
1)数据准备,在/opt/module/hive/datas目录下创建emp_sex.txt,添加如下内容

vim emp_sex.txt
悟空,A,男
大海,A,男
宋宋,B,男
凤姐,A,女
婷姐,B,女
婷婷,B,

2)创建emp_sex表并导入数据

create table emp_sex(
name string, 
dept_id string, 
sex string
) 
row format delimited fields terminated by ",";load data local inpath '/opt/module/hive/datas/emp_sex.txt' into table emp_sex;

3)需求:求出不同部门男女各多少人。结果如下

select dept_id,sum(case sex when '男' then 1 else 0 end) man_num,sum(case sex when '女' then 1 else 0 end) woman_num
from emp_sex
group by  dept_id;

8.2.3 行转列

在这里插入图片描述
1、相关函数说明
1)CONCAT(string A/col,string B/col…)

select concat('abc','def') from src limit 1;
'abcdef'

2)CONCAT_WS(separator,str1,str2,…)

select concat_ws('.','www',array('facebook','com')) from src limit 1;
'www.facebook.com'

3)COLLECT_SET(col):去重汇总
4)COLLECT_LIST(col):汇总
2、案例
1)需求:把星座和血型一样的人归类到一起。结果如下:

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

2)数据准备

vim person_info.txt
孙悟空,白羊座,A
大海,射手座,A
宋宋,白羊座,B
猪八戒,白羊座,A
凤姐,射手座,A
苍老师,白羊座,B

3)操作

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

按需求查询结果

SELECT
t1.c_b,
CONCAT_WS("|",collect_set(t1.name))
FROM (
SELECT
NAME ,
CONCAT_WS(',',constellation,blood_type) c_b
FROM person_info
)t1 
GROUP BY t1.c_b

8.2.4 列转行

在这里插入图片描述
1、函数说明
1)EXPLODE(col):将hive表的一列中复杂的array或者map结构拆分成多行
2)SPLIT(string str,string regex):按照reget字符串分割str,会返回分割后的字符串数组

 SELECT split('oneAtwoBthreeC', '[ABC]') FROM src LIMIT 1;["one", "two", "three"]

3)LATERAL VIEW:对拆分后的数据进行聚合
2、案例
1)需求

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

2)原始数据

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

3)操作

vim movie_info.txt
《疑犯追踪》	悬疑,动作,科幻,剧情
《Lie to me》	悬疑,警匪,动作,心理,剧情
《战狼2》	战争,动作,灾难create table movie_info(movie string, category string) 
row format delimited
fields terminated by "\t";load data local inpath "/opt/module/hive/datas/movie_info.txt" into table movie_info;

4)按需求查询数据

SELECT movie,category_name 
FROM movie_info 
lateral VIEW
explode(split(category,",")) movie_info_tmp  AS category_name ;

8.2.5 窗口函数(开窗函数)

1、介绍
输入多行数据(一个窗口),为每行数据进行一次计算,返回一个值。灵活运用窗口函数可以解决如去重,排序等。
在这里插入图片描述
2、语法

Function (arg1 ...) over ([patition by arg1 ...] [order by arg1 ...] [<window_expression>])
FunctionOver()window_expression
支持的函数指定分析函数工作的数据窗口大小,窗口会随着行的变化而变化窗口边界的设置
聚合函数:sum()、max()等partition by:表示将数据先按字段进行分区n preceding : 向前n行 n following:向后n行 current row:当前行
排序函数:rank()、row_number()等Order by:表示将各个分区内的数据按字段进行排序unbounded preceding:从前面的起点开始 unbounded following:到后面的终点结束
统计比较函数:lead()、lag()等

3、数据准备
1)在/opt/module/hive/datas目录下创建business.txt,添加如下内容

vim business.txt
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

2)创建hive表并导入数据

create table business(
name string, 
orderdate string,
cost int
)
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ',';load data local inpath "/opt/module/hive/datas/business.txt" into table business;

4、实例
1)需求:查询在2017年4月份购买过的顾客,及总人数
(1)样例

name    consume_num
mart    2
jack    2
select 
name, 
count(name) over() 
from business 
where subString(orderdate,1,7) = '2017-04'
group by name;

2)需求:查询顾客的购买明细及月购买总额
(1)样例

name    orderdate       cost    month_sum
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

(2)分析
查询顾客的购买明细,即表中的所有的列,分别以name和orderdate分组,显然group by无法满足我们。这里我们用到over(partition by arg1)指定窗口函数的分区字段,在分区基础上进行窗口分析。
(3)案例

select 
name,
orderdate,
cost,
sum(cost) over(partition by name,month(orderdate)) 
from business;
OK
name    orderdate       cost    sum_window_0	
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按照日期进行累加
计算表business的消费总额

select 
name,
orderdate,
cost, 
sum(cost) over() sample1 
from business;

在这里插入图片描述
计算每个人的销售总额
select
name,
orderdate,
cost,
sum(cost) over(partition by name) as sample2
from business;在这里插入图片描述
计算每个人截至到当天的消费总额

select 
name,
orderdate,
cost,
sum(cost) over(partition by name order by orderdate) as sample3 from business;

在这里插入图片描述
计算每个人截至到今天的消费总额(另一种写法)

select 
name,
orderdate,
cost, 
sum(cost) over(partition by name order by orderdate rows between UNBOUNDED PRECEDING and current row ) as sample4
from business;

计算每个人连续两天的消费总额

select 
name,
orderdate,
cost, 
sum(cost) over(partition by name order by orderdate rows between 1 PRECEDING and current row ) as sample5
from business;

在这里插入图片描述
计算每个人从当前天到最后一天的消费总额

select 
name,
orderdate,
cost,
sum(cost) over(partition by name order by orderdate rows between current row and UNBOUNDED FOLLOWING ) as sample6 from business;.

在这里插入图片描述
rows必须跟在Order by子句之后,对排序的结果进行限制,使用固定的行数来限制分区中的数量行数量。
4)需求:查看顾客上次的购买时间
(1)样例

name    orderdate       cost    last_time
jack    2017-01-01      10      (…………………)
jack    2017-01-05      46      2017-01-01
jack    2017-01-08      55      2017-01-05

(2)函数介绍

LAG (scalar_expression[,offset] [,default]) OVER ([query_partition_clause] order_by_clause);

解释:
Lag函数用于统计窗口内往上第n行值,参数scalar_pexpression为列名,参数offset为往上几行,参数default是设置的默认值(当往上第n行为NULL时,取默认值,否则就为NULL)
(3)案例代码

select
name,
orderdate,
cost,
lag(orderdate,1,'1900-01-01') over(partition by name order by orderdate ) as last_time
from business;
OK
name    orderdate       cost    last_time
jack    2017-01-01      10      1900-01-01
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      1900-01-01

5)需求:查询前20%时间的订单信息
(1)分析
当前表中总共有14行数据,前20%,就是大约前三行,你会觉得很简单,将数据orderdate字段排序取前三即可,但是表中数据量持续变化,前20%的数据是变化的,这里需要使用ntile函数。
(2)函数介绍
Ntile函数,为已排序的行,均分为指定数量的组,组号按顺序排列,返回组号,不支持rows between
(3)案例

select
t1.name,
t1.orderdate,
t1.cost
from (
select
name,
orderdate,
cost,
ntile(5) over(order by orderdate) sorted from business
) t1
where t1.sorted = 1;
OK
t.name  t.orderdate     t.cost
jack    2017-01-01      10
tony    2017-01-02      15
tony    2017-01-04      29

8.2.6 Rank

1、函数说明
1)RANK():排序相同时会重复,总数不会变。重复的名次一样但是下一名名次会以前面人数+1来定
2)DENSE_RANK():排序相同时会重复,总数会减少。就是若有重复则最后一名的名词不会和总数相等 即并列
3)ROW_NUMBER():会根据顺序计算,字段相同就按排头字段继续排
2、数据准备
1)数据

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

2)导入数据

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

3、需求:计算每门学科成绩排名

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;
OK
name    subject score   rp      drp     rmp
孙悟空  数学    95      1       1       1
宋宋    数学    86      2       2       2
婷婷    数学    85      3       3       3
大海    数学    56      4       4       4
宋宋    英语    84      1       1       1
大海    英语    84      1       1       2
婷婷    英语    78      3       2       3
孙悟空  英语    68      4       3       4
大海    语文    94      1       1       1
孙悟空  语文    87      2       2       2
婷婷    语文    65      3       3       3
宋宋    语文    64      4       4       4

8.3 自定义函数

1、内置函数:比如max/min等
2、根据用户自定义函数类别分为以下三种:
1)UDF:一进一出
2)UDAF:聚合函数,多进一出,类似:count/max/min
3)UDTF:炸裂函数,一进多出,类似:explode()
3、编程步骤
1)继承Hive提供的类
2)实现类中的抽象方法
3)在hive的命令行窗口创建函数
4、hive中引入自定义函数步骤
1)添加jar

add jar linux_jar_path

2)创建function

create [temporary] function [dbname.]function_name AS class_name;

3)在hive的命令行窗口删除函数

drop [temporary] function [if exists] [dbname.]function_name;

8.4 自定义UDF函数

1、需求:自定义一个UDF实现计算给定字符串的长度,例如:

select my_len("abcd");
ok
4

2、案例
1)创建Maven工程Hive
2)在工程项目的pom.xml文件中导入依赖
hive-exec
3)创建一个类

package com.atguigu.hive;import org.apache.hadoop.hive.ql.exec.UDFArgumentException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException;
import org.apache.hadoop.hive.ql.exec.UDFArgumentTypeException;
import org.apache.hadoop.hive.ql.metadata.HiveException;
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF;
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector;
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory;/*** 自定义UDF函数,需要继承GenericUDF类* 需求: 计算指定字符串的长度*/
public class MyStringLength extends GenericUDF {/**** @param arguments 输入参数类型的鉴别器对象* @return 返回值类型的鉴别器对象* @throws UDFArgumentException*/@Overridepublic ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException {// 判断输入参数的个数if(arguments.length !=1){throw new UDFArgumentLengthException("Input Args Length Error!!!");}// 判断输入参数的类型if(!arguments[0].getCategory().equals(ObjectInspector.Category.PRIMITIVE)){throw new UDFArgumentTypeException(0,"Input Args Type Error!!!");}//函数本身返回值为int,需要返回int类型的鉴别器对象return PrimitiveObjectInspectorFactory.javaIntObjectInspector;}/*** 函数的逻辑处理* @param arguments 输入的参数* @return 返回值* @throws HiveException*/@Overridepublic Object evaluate(DeferredObject[] arguments) throws HiveException {if(arguments[0].get() == null){return 0 ;}return arguments[0].get().toString().length();}@Overridepublic String getDisplayString(String[] children) {return "";}
}

4)打包jar包上传到服务器/opt/module/hive/datas/myudf.jar
5)将jar包添加到hive的classpath

add jar /opt/module/hive/datas/myudf.jar;

8.5 创建临时函数

1、创建临时函数与开发好的java class关联

create temporary function my_len as "com.atguigu.hive. MyStringLength";

2、在hql中使用自定义的函数

select ename,my_len(ename) ename_len from emp;
OK
ename   _c1
fanfan  6
SMITH   5
ALLEN   5
WARD    4
JONES   5
MARTIN  6
BLAKE   5
CLARK   5
SCOTT   5
KING    4
TURNER  6
ADAMS   5
JAMES   5
FORD    4
MILLER  6

注意:临时函数只跟会话有关系,跟库没有关系,只有创建临时函数的会话不断,在当前会话下,任意一个库都可以使用,其他会话全部不能使用。

8.6 创建永久函数

注意:因为add jar 的方式本身也是临时生效,所以在创建永久函数的时候,需要执行路径

create function my_len2 
as "com.atguigu.hive.udf.MyUDF" 
using jar "hdfs://hadoop102:8020/udf/myudf.jar";

即可在hql中使用自定义的永久函数

select ename,my_len2(ename) ename_len 
from emp;

删除永久函数

drop function my_len2;

注意:永久函数跟会话没有关系,创建函数的会话断了以后,其他会话也可以使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/624110.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

htmx 只是另一个 JavaScript 框架吗?老外都吵上了

对 htmx 最常见的批评之一通常来自第一次听说它的人&#xff0c;如下所示&#xff1a; 你抱怨现代前端框架的复杂性&#xff0c;但你的解决方案只是另一个复杂的前端框架。 这是一个很好的反对意见&#xff01;对于你引入到项目中的任何第三方 (3P) 代码&#xff0c;你都有权提…

HarmonyOS 开发基础(八)Row和Column

HarmonyOS 开发基础&#xff08;八&#xff09;Row和Column 一、Column 容器 1、容器说明&#xff1a; 纵向容器主轴方向&#xff1a;从上到下纵向交叉轴方向&#xff1a;从左到右横向 2、容器属性&#xff1a; justifyContent&#xff1a;设置子元素在主轴方向的对齐格式…

实例分割论文精读:Mask R-CNN

1.摘要 本文提出了一种概念简单、灵活、通用的实例分割方法&#xff0c;该方法在有效地检测图像中的物体同时&#xff0c;为每个物体实例生成一个实例分割模板&#xff0c;添加了一个分支&#xff0c;用于预测一个对象遮罩&#xff0c;与现有的分支并行&#xff0c;用于边界框…

零知识证明的最新发展和应用

PrimiHub一款由密码学专家团队打造的开源隐私计算平台&#xff0c;专注于分享数据安全、密码学、联邦学习、同态加密等隐私计算领域的技术和内容。 当企业收集大量客户数据去审查、改进产品和服务以及将数据资产货币化时&#xff0c;他们容易受到网络攻击威胁&#xff0c;造成数…

RC4加解密源码

本文介绍RC4加解密源码。 RC4&#xff08;来自Rivest Cipher 4的缩写&#xff09;是一种流加密算法&#xff0c;密钥长度可变。它加解密使用相同的密钥&#xff0c;因此也属于对称加密算法。RC4具有加解密速度快&#xff0c;算法简单等优点&#xff0c;在算力不高场合&#xf…

昇腾910b部署Chatglm3-6b进行流式输出【pytorch框架】NPU推理

文章目录 准备阶段避坑阶段添加代码结果展示 准备阶段 配套软件包Ascend-cann-toolkit和Ascend-cann-nnae适配昇腾的Pytorch适配昇腾的Torchvision Adapter下载ChatGLM3代码下载chatglm3-6b模型&#xff0c;或在modelscope里下载 避坑阶段 每个人的服务器都不一样&#xff0…

Pixart PAR2861 蓝牙 keyboard 开发笔记

Pixart PAR2861 是一款采用32 bits ARM Cortex-M0 低功耗、高效能 2.4GHz RF 的 SoC。 该 SoC 整合了高效能的 2.4GHz RF 收发器、硬体Keyscan、硬体按键防弹跳、SPI、I2C、PWM LED、ADC、UART等。内建 DC/DC 转换器和 LDO 为独立 HID 应用提供完整的低功耗 SoC 解决方案。 1.…

2023年网络安全事件处罚盘点,文件销毁 硬盘销毁 物料销毁

《中华人民共和国网络安全法》是我国第一部全面规范网络空间安全管理方面问题的基础性法律&#xff0c;是我国网络空间法治建设的重要里程碑&#xff0c;《中华人民共和国网络安全法》从2013年下半年提上日程&#xff0c;到2016年年底颁布&#xff0c;自2017年6月1日起施行&…

滑动登陆注册同页面

这是一个登陆注册在同一个页面滑动选择的页面 技术&#xff1a;html、css、javascript 简单页面实现&#xff08;为了方便&#xff0c;已将代码放在同一文件引用&#xff09;&#xff1a; 1.1、效果图 1.2、完整代码&#xff1a; <!DOCTYPE html> <html lang"…

virtualbox Ubuntu 网络连接

一、网络连接需求1—— 上网&#xff1a; 虚拟机默认的NAT连接方式&#xff0c;几乎不需要怎么配置&#xff0c;即可实现上网。 enp0s17以太网必须要开启&#xff0c;才能上网&#xff1b; 但是主机ping不通虚拟机&#xff0c;貌似可以ping 127.0.0.1; 二、主机和虚拟机相互p…

语境化语言表示模型-ELMO、BERT、GPT、XLnet

一.语境化语言表示模型介绍 语境化语言表示模型&#xff08;Contextualized Language Representation Models&#xff09;是一类在自然语言处理领域中取得显著成功的模型&#xff0c;其主要特点是能够根据上下文动态地学习词汇和短语的表示。这些模型利用了上下文信息&#xf…

DrGraph原理示教 - OpenCV 4 功能 - 形态操作

形态类型 从OpenCV图像处理基本知识来看&#xff0c;膨胀腐蚀操作后&#xff0c;还有形态操作&#xff0c;如开运算、闭运算、梯度、礼帽与黑帽&#xff0c;感觉很多&#xff0c;其实&#xff0c;本质上就是批处理操作&#xff0c;如 开运算&#xff1a;先腐蚀&#xff0c;再膨…

大模型LLM Agent在 Text2SQL 应用上的实践

1.前言 在上篇文章中「如何通过Prompt优化Text2SQL的效果」介绍了基于Prompt Engineering来优化Text2SQL效果的实践&#xff0c;除此之外我们还可以使用Agent来优化大模型应用的效果。 本文将从以下4个方面探讨通过AI Agent来优化LLM的Text2SQL转换效果。 1 Agent概述2 Lang…

肯尼斯·里科《C和指针》第6章 指针(3)

肯尼斯里科《C和指针》第6章 指针&#xff08;1&#xff09;-CSDN博客 肯尼斯里科《C和指针》第6章 指针&#xff08;2&#xff09;-CSDN博客 前置知识&#xff1a;左值右值 为了理解有些操作符存在的限制&#xff0c;必须理解左值(L-value)和右值(R-value)之间的区别。这两个…

2024年百场进校公益安全培训开启

自2023年年底&#xff0c;上海风暴救援队积极策划并推动了2024年的“百场进校传安全”培训项目。经过在东方锦绣于2023年12月14日、上钢新村幼儿园于2023年12月28日的先期测试&#xff0c;项目于2024年1月5日在齐河路幼儿园正式启动。随后&#xff0c;于2024年1月11日在浦南幼儿…

顺序表和链表基础

定义动态的顺序表 typedef int SLDataType; typedef struct Seqlist {SLDataType* array;size_t size;size_t capacity; }Seqlist; 在顺序表中插入数据 bool ListInsert(Seqlist* l, int i, SLDataType e) {if (i < 1 || i > l->capacity)return false;int j;for (…

【大数据进阶第三阶段之Hue学习笔记】Hue的安装和使用

1、 Hue的安装 1.1 上传解压安装包 Hue的安装支持多种方式&#xff0c;包括rpm包的方式进行安装、tar.gz包的方式进行安装以及cloudera manager的方式来进行安装等&#xff0c;我们这里使用tar.gz包的方式来进行安装 Hue的压缩包的下载地址&#xff1a; http://archive.cloude…

python绘制热力图-数据处理-VOC数据类别标签分布及数量统计(-代码)

Python是一种功能强大的编程语言&#xff0c;它提供了许多库和工具&#xff0c;用于处理和可视化数据。在本文中&#xff0c;我们将介绍使用Python绘制热力图&#xff0c;并对VOC数据集中的类别标签进行分布及数量统计。 首先&#xff0c;我们需要导入所需的库。使用numpy库来…

查找算法(部分)

顺序查找 顺序查找是最简单的了&#xff0c;属于无序查找算法&#xff0c;它的原理就是从前往后一个一个的找&#xff0c;如果找到了就返回它的位置&#xff0c;否则就返回-1。 如果有多个相同元素的话&#xff0c;返回第一个该元素的位置。 代码&#xff1a; #include<…

Vue3 中使用 Vuex 和 Pinia 对比之 Vuex的用法

本文基于 Vue3 的 composition API 来展开 Vuex 和 Pinia 的用法比较 Pinia传送门 Vuex传送门 Vuex 状态管理的核心概念 状态- 驱动应用的数据源&#xff1b;视图 - 以声明方式将状态映射到视图&#xff1b;操作 - 响应在视图上的用户输入导致的状态变化 下面是源自Vuex 官…