小言_互联网的博客

一文学完所有的Hive Sql(两万字最全详解)

208人阅读  评论(0)

 

Hive Sql 大全

 

本文基本涵盖了Hive日常使用的所有SQL,因为SQL太多,所以将SQL进行了如下分类: 一、DDL语句(数据定义语句):
对数据库的操作:包含创建、修改数据库
对数据表的操作:分为内部表及外部表,分区表和分桶表
二、DQL语句(数据查询语句):
单表查询、关联查询
hive函数:包含聚合函数,条件函数,日期函数,字符串函数等
行转列及列转行:lateral view 与 explode 以及 reflect
窗口函数与分析函数
其他一些窗口函数

文章首发于公众号【五分钟学大数据】,大数据领域原创技术号,每周更新大数据技术文及面试真题解析,关注后可领取精心制作大数据面试宝典!

hive的DDL语法

对数据库的操作

  • 创建数据库:


  
  1. create  database  if  not  exists myhive;
  2. 说明:hive的表存放位置模式是由hive-site.xml当中的一个属性指定的 :hive.metastore.warehouse.dir
  3. 创建数据库并指定hdfs存储位置 :
  4. create  database myhive2 location  '/myhive2';
  • 修改数据库:

alter  database  myhive2  set  dbproperties('createtime'='20210329');

说明:可以使用alter database 命令来修改数据库的一些属性。但是数据库的元数据信息是不可更改的,包括数据库的名称以及数据库所在的位置

  • 查看数据库详细信息


  
  1. 查看数据库基本信息
  2. hive (myhive)>  desc   database   myhive2;
  3. 查看数据库更多详细信息
  4. hive (myhive)>  desc  database  extended   myhive2;
  • 删除数据库


  
  1. 删除一个空数据库,如果数据库下面有数据表,那么就会报错
  2. drop   database  myhive2;
  3. 强制删除数据库,包含数据库下面的表一起删除
  4. drop   database  myhive   cascade

对数据表的操作

对管理表(内部表)的操作:

  • 建内部表:


  
  1. hive (myhive)>  use  myhive-- 使用 myhive数据库
  2. hive (myhive)>  create  table  stu(id int,name string);
  3. hive (myhive)>  insert  into  stu  values ( 1, "zhangsan");
  4. hive (myhive)>  insert  into  stu  values ( 1, "zhangsan"),( 2, "lisi");   -- 一次插入多条数据
  5. hive (myhive)>  select *  from  stu;
  • hive建表时候的字段类型:

分类 类型 描述 字面量示例
原始类型 BOOLEAN true/false TRUE
  TINYINT 1字节的有符号整数 -128~127 1Y
  SMALLINT 2个字节的有符号整数,-32768~32767 1S
  INT 4个字节的带符号整数 1
  BIGINT 8字节带符号整数 1L
  FLOAT 4字节单精度浮点数1.0  
  DOUBLE 8字节双精度浮点数 1.0
  DEICIMAL 任意精度的带符号小数 1.0
  STRING 字符串,变长 “a”,’b’
  VARCHAR 变长字符串 “a”,’b’
  CHAR 固定长度字符串 “a”,’b’
  BINARY 字节数组 无法表示
  TIMESTAMP 时间戳,毫秒值精度 122327493795
  DATE 日期 ‘2016-03-29’
  INTERVAL 时间频率间隔  
复杂类型 ARRAY 有序的的同类型的集合 array(1,2)
  MAP key-value,key必须为原始类型,value可以任意类型 map(‘a’,1,’b’,2)
  STRUCT 字段集合,类型可以不同 struct(‘1’,1,1.0), named_stract(‘col1’,’1’,’col2’,1,’clo3’,1.0)
  UNION 在有限取值范围内的一个值 create_union(1,’a’,63)

对decimal类型简单解释下
用法:decimal(11,2) 代表最多有11位数字,其中后2位是小数,整数部分是9位;如果整数部分超过9位,则这个字段就会变成null;如果小数部分不足2位,则后面用0补齐两位,如果小数部分超过两位,则超出部分四舍五入
也可直接写 decimal,后面不指定位数,默认是 decimal(10,0) 整数10位,没有小数

  • 创建表并指定字段之间的分隔符

create  table if not exists stu2(id int ,name stringrow format delimited fields terminated by '\t' stored as textfile location '/user/stu2';

row format delimited fields terminated by '\t' 指定字段分隔符,默认分隔符为 '\001'
stored as 指定存储格式
location 指定存储位置

  • 根据查询结果创建表

create table stu3 as select * from stu2;
  • 根据已经存在的表结构创建表

create table stu4 like stu2;
  • 查询表的结构


  
  1. 只查询表内字段及属性
  2. desc stu2;
  3. 详细查询
  4. desc formatted  stu2;
  • 查询创建表的语句

show create table stu2;

对外部表操作

外部表因为是指定其他的hdfs路径的数据加载到表当中来,所以hive表会认为自己不完全独占这份数据,所以删除hive表的时候,数据仍然存放在hdfs当中,不会删掉,只会删除表的元数据

  • 构建外部表

create external table student (s_id string,s_name stringrow format delimited fields terminated by '\t';
  • 从本地文件系统向表中加载数据


  
  1. 追加操作
  2. load  data  local inpath  '/export/servers/hivedatas/student.csv'  into  table student;
  3. 覆盖操作
  4. load  data  local inpath  '/export/servers/hivedatas/student.csv' overwrite   into  table student;
  • 从hdfs文件系统向表中加载数据


  
  1. load  data inpath  '/hivedatas/techer.csv'  into  table techer;
  2. 加载数据到指定分区
  3. load  data inpath  '/hivedatas/techer.csv'  into  table techer  partition(cur_date= 20201210);
  • 注意
    1.使用 load data local 表示从本地文件系统加载,文件会拷贝到hdfs上
    2.使用 load data 表示从hdfs文件系统加载,文件会直接移动到hive相关目录下,注意不是拷贝过去,因为hive认为hdfs文件已经有3副本了,没必要再次拷贝了
    3.如果表是分区表,load 时不指定分区会报错
    4.如果加载相同文件名的文件,会被自动重命名

对分区表的操作

  • 创建分区表的语法

create table score(s_id string, s_score int) partitioned by (month string);
  • 创建一个表带多个分区

create table score2 (s_id string, s_score int) partitioned by (year string,month string,day string);

注意:
hive表创建的时候可以用 location 指定一个文件或者文件夹,当指定文件夹时,hive会加载文件夹下的所有文件,当表中无分区时,这个文件夹下不能再有文件夹,否则报错
当表是分区表时,比如 partitioned by (day string), 则这个文件夹下的每一个文件夹就是一个分区,且文件夹名为 day=20201123 这种格式,然后使用:msck repair table score; 修复表结构,成功之后即可看到数据已经全部加载到表当中去了

  • 加载数据到一个分区的表中

load data local inpath '/export/servers/hivedatas/score.csv' into table score partition (month='201806');
  • 加载数据到一个多分区的表中去

load data local inpath '/export/servers/hivedatas/score.csv' into table score2 partition(year='2018',month='06',day='01');
  • 查看分区

show  partitions  score;
  • 添加一个分区

alter table score add partition(month='201805');
  • 同时添加多个分区

 alter table score add partition(month='201804'partition(month = '201803');

注意:添加分区之后就可以在hdfs文件系统当中看到表下面多了一个文件夹

  • 删除分区

 alter table score drop partition(month = '201806');

对分桶表操作

将数据按照指定的字段进行分成多个桶中去,就是按照分桶字段进行哈希划分到多个文件当中去
分区就是分文件夹,分桶就是分文件

分桶优点:
1. 提高join查询效率
2. 提高抽样效率

  • 开启hive的捅表功能

set hive.enforce.bucketing=true;
  • 设置reduce的个数

set mapreduce.job.reduces=3;
  • 创建桶表

create table course (c_id string,c_name string) clustered by(c_id) into 3 buckets;

桶表的数据加载:由于桶表的数据加载通过hdfs dfs -put文件或者通过load data均不可以,只能通过insert overwrite 进行加载
所以把文件加载到桶表中,需要先创建普通表,并通过insert overwrite的方式将普通表的数据通过查询的方式加载到桶表当中去

  • 通过insert overwrite给桶表中加载数据

insert overwrite table course select * from course_common cluster by(c_id);  -- 最后指定桶字段

修改表和删除表

  • 修改表名称

alter  table  old_table_name  rename  to  new_table_name;
  • 增加/修改列信息


  
  1. 查询表结构
  2. desc score5;
  3. 添加列
  4. alter  table score5  add  columns (mycol  string, mysco  string);
  5. 更新列
  6. alter  table score5  change  column mysco mysconew  int;
  • 删除表操作

drop table score5;
  • 清空表操作


  
  1. truncate  table score6;
  2. 说明:只能清空管理表,也就是内部表;清空外部表,会产生错误

注意:truncate 和 drop:
如果 hdfs 开启了回收站,drop 删除的表数据是可以从回收站恢复的,表结构恢复不了,需要自己重新创建;truncate 清空的表是不进回收站的,所以无法恢复truncate清空的表
所以 truncate 一定慎用,一旦清空将无力回天

向hive表中加载数据

  • 直接向分区表中插入数据

insert into table score partition(month ='201807'values ('001','002','100');
  • 通过load方式加载数据

 load data local inpath '/export/servers/hivedatas/score.csv' overwrite into table score partition(month='201806');
  • 通过查询方式加载数据

insert overwrite table score2 partition(month = '201806'select s_id,c_id,s_score from score1;
  • 查询语句中创建表并加载数据

create table score2 as select * from score1;
  • 在创建表是通过location指定加载数据的路径

create external table score6 (s_id string,c_id string,s_score introw format delimited fields terminated by ',' location '/myscore';
  • export导出与import 导入 hive表数据(内部表操作)


  
  1. create  table techer2 like techer;  --依据已有表结构创建表
  2. export  table techer to   '/export/techer';
  3. import  table techer2 from  '/export/techer';

hive表中数据导出

  • insert导出


  
  1. 将查询的结果导出到本地
  2. insert overwrite  local  directory  '/export/servers/exporthive'  select *  from score;
  3. 将查询的结果格式化导出到本地
  4. insert overwrite  local  directory  '/export/servers/exporthive'  row  format  delimited  fields  terminated  by  '\t' collection items  terminated  by  '#'  select *  from student;
  5. 将查询的结果导出到HDFS上(没有local)
  6. insert overwrite  directory  '/export/servers/exporthive'  row  format  delimited  fields  terminated  by  '\t' collection items  terminated  by  '#'  select *  from score;
  • Hadoop命令导出到本地

dfs -get /export/servers/exporthive/000000_0 /export/servers/exporthive/local.txt;
  • hive shell 命令导出


  
  1. 基本语法:(hive -f/-e 执行语句或者脚本 > file)
  2. hive -e  "select * from myhive.score;" >  /export/servers/exporthive/score.txt
  3. hive -f  export.sh >  /export/servers/exporthive/score.txt
  • export导出到HDFS上

export table score to '/export/exporthive/score';

hive的DQL查询语法

单表查询


  
  1. SELECT [ ALL |  DISTINCT] select_expr, select_expr, ... 
  2. FROM table_reference
  3. [ WHERE where_condition] 
  4. [ GROUP  BY col_list [ HAVING condition]] 
  5. [CLUSTER  BY col_list 
  6.   | [ DISTRIBUTE  BY col_list] [ SORT  BYORDER  BY col_list] 
  7. [ LIMIT  number]

注意:
1、order by 会对输入做全局排序,因此只有一个reducer,会导致当输入规模较大时,需要较长的计算时间。
2、sort by不是全局排序,其在数据进入reducer前完成排序。因此,如果用sort by进行排序,并且设置mapred.reduce.tasks>1,则sort by只保证每个reducer的输出有序,不保证全局有序。
3、distribute by(字段)根据指定的字段将数据分到不同的reducer,且分发算法是hash散列。
4、Cluster by(字段) 除了具有Distribute by的功能外,还会对该字段进行排序。
因此,如果分桶和sort字段是同一个时,此时,cluster by = distribute by + sort by

  • WHERE语句

select * from score where s_score < 60;

注意:
小于某个值是不包含null的,如上查询结果是把 s_score 为 null 的行剔除的

  • GROUP BY 分组


  
  1. select s_id , avg(s_score)  from score  group  by s_id;
  2. 分组后对数据进行筛选,使用having
  3.   select s_id , avg(s_score) avgscore  from score  group  by s_id  having avgscore >  85;

注意:
如果使用 group by 分组,则 select 后面只能写分组的字段或者聚合函数
where和having区别:
1 having是在 group by 分完组之后再对数据进行筛选,所以having 要筛选的字段只能是分组字段或者聚合函数
2 where 是从数据表中的字段直接进行的筛选的,所以不能跟在gruop by后面,也不能使用聚合函数

  • join 连接


  
  1. INNER JOIN 内连接:只有进行连接的两个表中都存在与连接条件相匹配的数据才会被保留下来
  2. select *  from techer t [ innerjoin course c  on t.t_id = c.t_id;  -- inner 可省略
  3. LEFT OUTER JOIN 左外连接:左边所有数据会被返回,右边符合条件的被返回
  4. select *  from techer t  left  join course c  on t.t_id = c.t_id;  -- outer可省略
  5. RIGHT OUTER JOIN 右外连接:右边所有数据会被返回,左边符合条件的被返回、
  6. select *  from techer t  right  join course c  on t.t_id = c.t_id;
  7. FULL OUTER JOIN 满外(全外)连接: 将会返回所有表中符合条件的所有记录。如果任一表的指定字段没有符合条件的值的话,那么就使用NULL值替代。
  8. SELECT *  FROM techer t  FULL  JOIN course c  ON t.t_id = c.t_id ;

注:1. hive2版本已经支持不等值连接,就是 join on条件后面可以使用大于小于符号了;并且也支持 join on 条件后跟or (早前版本 on 后只支持 = 和 and,不支持 > < 和 or)
2.如hive执行引擎使用MapReduce,一个join就会启动一个job,一条sql语句中如有多个join,则会启动多个job

注意:表之间用逗号(,)连接和 inner join 是一样的
select * from table_a,table_b where table_a.id=table_b.id;
它们的执行效率没有区别,只是书写方式不同,用逗号是sql 89标准,join 是sql 92标准。用逗号连接后面过滤条件用 where ,用 join 连接后面过滤条件是 on。

  • order by 排序


  
  1. 全局排序,只会有一个reduce
  2. ASC(ascend): 升序(默认) DESC(descend): 降序
  3. SELECT *  FROM student s  LEFT  JOIN score sco  ON s.s_id = sco.s_id  ORDER  BY sco.s_score  DESC;

注意:order by 是全局排序,所以最后只有一个reduce,也就是在一个节点执行,如果数据量太大,就会耗费较长时间

  • sort by 局部排序


  
  1. 每个MapReduce内部进行排序,对全局结果集来说不是排序。
  2. 设置reduce个数
  3. set mapreduce.job.reduces= 3;
  4. 查看设置reduce个数
  5. set mapreduce.job.reduces;
  6. 查询成绩按照成绩降序排列
  7. select *  from score  sort  by s_score;
  8.  
  9. 将查询结果导入到文件中(按照成绩降序排列)
  10. insert overwrite  local  directory  '/export/servers/hivedatas/sort'  select *  from score  sort  by s_score;
  • distribute by 分区排序


  
  1. distribute by:类似MR中partition,进行分区,结合sort by使用
  2. 设置reduce的个数,将我们对应的s_id划分到对应的reduce当中去
  3. set mapreduce.job.reduces= 7;
  4. 通过distribute by  进行数据的分区
  5. select *  from score  distribute  by s_id  sort  by s_score;

注意:Hive要求 distribute by 语句要写在 sort by 语句之前

  • cluster by


  
  1. 当distribute  by和sort  by字段相同时,可以使用cluster  by方式.
  2. cluster  by除了具有distribute  by的功能外还兼具sort  by的功能。但是排序只能是正序排序,不能指定排序规则为ASC或者DESC。
  3. 以下两种写法等价
  4. select *  from score cluster  by s_id;
  5. select *  from score distribute  by s_id sort  by s_id;

Hive函数

聚合函数

hive支持 count(),max(),min(),sum(),avg() 等常用的聚合函数

注意:
聚合操作时要注意null值
count(*) 包含null值,统计所有行数
count(id) 不包含null值
min 求最小值是不包含null,除非所有值都是null
avg 求平均值也是不包含null

  • 非空集合总体变量函数: var_pop


  
  1. 语法: var_pop(col)
  2. 返回值: double
  3. 说明: 统计结果集中col非空集合的总体变量(忽略null)
  • 非空集合样本变量函数: var_samp


  
  1. 语法: var_samp (col)
  2. 返回值: double
  3. 说明: 统计结果集中col非空集合的样本变量(忽略null)
  • 总体标准偏离函数: stddev_pop


  
  1. 语法: stddev_pop(col)
  2. 返回值: double
  3. 说明: 该函数计算总体标准偏离,并返回总体变量的平方根,其返回值与VAR_POP函数的平方根相同
  • 中位数函数: percentile


  
  1. 语法: percentile(BIGINT col, p)
  2. 返回值: double
  3. 说明: 求准确的第pth个百分位数,p必须介于0和1之间,但是col字段目前只支持整数,不支持浮点数类型

关系运算


  
  1. 支持:等值(=)、不等值(!= 或 <>)、小于(<)、小于等于(<=)、大于(>)、大于等于(>=)
  2. 空值判断( is  null)、非空判断( is not  null)
  • LIKE比较: LIKE


  
  1. 语法: A LIKE B
  2. 操作类型: strings
  3. 描述: 如果字符串A或者字符串B为 NULL,则返回 NULL;如果字符串A符合表达式B 的正则语法,则为 TRUE;否则为 FALSE。B中字符”_”表示任意单个字符,而字符”%”表示任意数量的字符。
  • JAVA的LIKE操作: RLIKE


  
  1. 语法: A RLIKE B
  2. 操作类型: strings
  3. 描述: 如果字符串A或者字符串B为 NULL,则返回 NULL;如果字符串A符合JAVA正则表达式B的正则语法,则为 TRUE;否则为 FALSE
  • REGEXP操作: REGEXP


  
  1. 语法: A REGEXP B
  2. 操作类型: strings
  3. 描述: 功能与RLIKE相同
  4. 示例: select  1  from tableName  where  'footbar' REGEXP  '^f.*r$';
  5. 结果:1

数学运算

支持所有数值类型:加(+)、减(-)、乘(*)、除(/)、取余(%)、位与(&)、位或(|)、位异或(^)、位取反(~)

逻辑运算

支持:逻辑与(and)、逻辑或(or)、逻辑非(not)

数值运算

  • 取整函数: round


  
  1. 语法: round( double a)
  2. 返回值: BIGINT
  3. 说明: 返回 double类型的整数值部分 (遵循四舍五入)
  4. 示例: select round(3.1415926from tableName;
  5. 结果: 3
  • 指定精度取整函数: round


  
  1. 语法: round( double a,  int d)
  2. 返回值: DOUBLE
  3. 说明: 返回指定精度d的 double类型
  4. hive>  select round(3.1415926,4from tableName;
  5. 3.1416
  • 向下取整函数: floor


  
  1. 语法: floor( double a)
  2. 返回值: BIGINT
  3. 说明: 返回等于或者小于该 double变量的最大的整数
  4. hive>  select floor(3.641from tableName;
  5. 3
  • 向上取整函数: ceil


  
  1. 语法: ceil( double a)
  2. 返回值: BIGINT
  3. 说明: 返回等于或者大于该 double变量的最小的整数
  4. hive>  select ceil(3.1415926from tableName;
  5. 4
  • 取随机数函数: rand


  
  1. 语法: rand(),rand( int seed)
  2. 返回值:  double
  3. 说明: 返回一个 01范围内的随机数。如果指定种子seed,则会等到一个稳定的随机数序列
  4. hive>  select rand(from tableName; -- 每次执行此语句得到的结果都不同
  5. 0.5577432776034763
  6. hive>  select rand(100) ;  -- 只要指定种子,每次执行此语句得到的结果一样的
  7. 0.7220096548596434
  • 自然指数函数: exp


  
  1. 语法:  exp( double a)
  2. 返回值:  double
  3. 说明: 返回自然对数e的a次方
  4. hive>  select exp(2) ;
  5. 7.38905609893065
  • 以10为底对数函数: log10


  
  1. 语法:  log10( double a)
  2. 返回值:  double
  3. 说明: 返回以 10为底的a的对数
  4. hive>  select log10(100) ;
  5. 2.0

此外还有:以2为底对数函数: log2()、对数函数: log()

  • 幂运算函数: pow


  
  1. 语法:  pow( double a,  double p)
  2. 返回值:  double
  3. 说明: 返回a的p次幂
  4. hive>  select pow(2,4) ;
  5. 16.0
  • 开平方函数: sqrt


  
  1. 语法:  sqrt( double a)
  2. 返回值:  double
  3. 说明: 返回a的平方根
  4. hive>  select sqrt(16) ;
  5. 4.0
  • 二进制函数: bin


  
  1. 语法: bin(BIGINT a)
  2. 返回值:  string
  3. 说明: 返回a的二进制代码表示
  4. hive>  select bin(7) ;
  5. 111

十六进制函数: hex()、将十六进制转化为字符串函数: unhex()
进制转换函数: conv(bigint num, int from_base, int to_base) 说明: 将数值num从from_base进制转化到to_base进制

此外还有很多数学函数: 绝对值函数: abs()、正取余函数: pmod()、正弦函数: sin()、反正弦函数: asin()、余弦函数: cos()、反余弦函数: acos()、positive函数: positive()、negative函数: negative()

条件函数

  • If函数: if


  
  1. 语法:  if(boolean testCondition,  T valueTrue,  T valueFalseOrNull)
  2. 返回值:  T
  3. 说明: 当条件testCondition为 TRUE时,返回valueTrue;否则返回valueFalseOrNull
  4. hive> select  if( 1= 2, 100, 200) ;
  5. 200
  6. hive> select  if( 1= 1, 100, 200) ;
  7. 100
  • 非空查找函数: coalesce


  
  1. 语法: coalesce( T v1,  T v2, …)
  2. 返回值:  T
  3. 说明: 返回参数中的第一个非空值;如果所有值都为 NULL,那么返回 NULL
  4. hive> select coalesce(null, '100', '50') ;
  5. 100
  • 条件判断函数:case when (两种写法,其一)


  
  1. 语法:  case  when a  then b [ when c  then d]* [ else e]  end
  2. 返回值: T
  3. 说明:如果a为TRUE,则返回b;如果c为TRUE,则返回d;否则返回e
  4. hive> select  case  when  1= 2  then  'tom'  when  2= 2  then  'mary'  else  'tim'  end from tableName;
  5. mary
  • 条件判断函数:case when (两种写法,其二)


  
  1. 语法:  case a  when b  then c [ when d  then e]* [ else f]  end
  2. 返回值: T
  3. 说明:如果a等于b,那么返回c;如果a等于d,那么返回e;否则返回f
  4. hive> Select  case  100  when  50  then  'tom'  when  100  then  'mary'  else  'tim'  end from tableName;
  5. mary

日期函数

注:以下SQL语句中的 from tableName 可去掉,不影响查询结果

    1. 获取当前UNIX时间戳函数: unix_timestamp


  
  1. 语法: unix_timestamp()
  2. 返回值: bigint
  3. 说明: 获得当前时区的UNIX时间戳
  4. hive>  select unix_timestamp(from tableName;
  5. 1616906976
    1. UNIX时间戳转日期函数: from_unixtime


  
  1. 语法: from_unixtime(bigint unixtime[,  string format])
  2. 返回值:  string
  3. 说明: 转化UNIX时间戳(从 1970 -01 -01  00: 00: 00 UTC到指定时间的秒数)到当前时区的时间格式
  4. hive>  select from_unixtime(1616906976,'yyyyMMdd'from tableName;
  5. 20210328
    1. 日期转UNIX时间戳函数: unix_timestamp


  
  1. 语法: unix_timestamp( string date)
  2. 返回值: bigint
  3. 说明: 转换格式为 "yyyy-MM-dd HH:mm:ss"的日期到UNIX时间戳。如果转化失败,则返回 0
  4. hive>   select unix_timestamp('2021-03-08 14:21:15'from tableName;
  5. 1615184475
    1. 指定格式日期转UNIX时间戳函数: unix_timestamp


  
  1. 语法: unix_timestamp( string date,  string pattern)
  2. 返回值: bigint
  3. 说明: 转换pattern格式的日期到UNIX时间戳。如果转化失败,则返回 0
  4. hive>   select unix_timestamp('2021-03-08 14:21:15','yyyyMMdd HH:mm:ss'from tableName;
  5. 1615184475
    1. 日期时间转日期函数: to_date


  
  1. 语法: to_date( string timestamp)
  2. 返回值:  string
  3. 说明: 返回日期时间字段中的日期部分。
  4. hive>  select to_date('2021-03-28 14:03:01'from tableName;
  5. 2021 -03 -28
    1. 日期转年函数: year


  
  1. 语法: year( string date)
  2. 返回值:  int
  3. 说明: 返回日期中的年。
  4. hive>  select year('2021-03-28 10:03:01'from tableName;
  5. 2021
  6. hive>  select year('2021-03-28'from tableName;
  7. 2021
    1. 日期转月函数: month


  
  1. 语法: month ( string date)
  2. 返回值:  int
  3. 说明: 返回日期中的月份。
  4. hive>  select month('2020-12-28 12:03:01'from tableName;
  5. 12
  6. hive>  select month('2021-03-08'from tableName;
  7. 8
    1. 日期转天函数: day


  
  1. 语法: day ( string date)
  2. 返回值:  int
  3. 说明: 返回日期中的天。
  4. hive>  select day('2020-12-08 10:03:01'from tableName;
  5. 8
  6. hive>  select day('2020-12-24'from tableName;
  7. 24
    1. 日期转小时函数: hour


  
  1. 语法:  hour ( string  date)
  2. 返回值:  int
  3. 说明: 返回日期中的小时。
  4. hive>  select  hour( '2020-12-08 10:03:01') from tableName;
  5. 10
    1. 日期转分钟函数: minute


  
  1. 语法:  minute ( string  date)
  2. 返回值:  int
  3. 说明: 返回日期中的分钟。
  4. hive>  select  minute( '2020-12-08 10:03:01') from tableName;
  5. 3
    1. 日期转秒函数: second


  
  1. 语法:  second ( string  date)
  2. 返回值:  int
  3. 说明: 返回日期中的秒。
  4. hive>  select  second( '2020-12-08 10:03:01') from tableName;
  5. 1
    1. 日期转周函数: weekofyear


  
  1. 语法: weekofyear ( string date)
  2. 返回值:  int
  3. 说明: 返回日期在当前的周数。
  4. hive>  select weekofyear('2020-12-08 10:03:01'from tableName;
  5. 49
    1. 日期比较函数: datediff


  
  1. 语法: datediff( string enddate,  string startdate)
  2. 返回值:  int
  3. 说明: 返回结束日期减去开始日期的天数。
  4. hive>  select datediff('2020-12-08','2012-05-09'from tableName;
  5. 213
    1. 日期增加函数: date_add


  
  1. 语法: date_add( string startdate,  int days)
  2. 返回值:  string
  3. 说明: 返回开始日期startdate增加days天后的日期。
  4. hive>  select date_add('2020-12-08',10from tableName;
  5. 2020 -12 -18
    1. 日期减少函数: date_sub


  
  1. 语法: date_sub ( string startdate,  int days)
  2. 返回值:  string
  3. 说明: 返回开始日期startdate减少days天后的日期。
  4. hive>  select date_sub('2020-12-08',10from tableName;
  5. 2020 -11 -28

字符串函数

    1. 字符串长度函数:length


  
  1. 语法: length( string A)
  2. 返回值:  int
  3. 说明:返回字符串A的长度
  4. hive>  select length('abcedfg'from tableName;
  5. 7
    1. 字符串反转函数:reverse


  
  1. 语法:  reverse( string A)
  2. 返回值:  string
  3. 说明:返回字符串A的反转结果
  4. hive>  select  reverse( 'abcedfg') from tableName;
  5. gfdecba
    1. 字符串连接函数:concat


  
  1. 语法: concat( string A,  string B…)
  2. 返回值:  string
  3. 说明:返回输入字符串连接后的结果,支持任意个输入字符串
  4. hive> select concat( 'abc', 'def’,'gh ')from tableName;
  5. abcdefgh
    1. 带分隔符字符串连接函数:concat_ws


  
  1. 语法: concat_ws( string SEP,  string A,  string B…)
  2. 返回值:  string
  3. 说明:返回输入字符串连接后的结果,SEP表示各个字符串间的分隔符
  4. hive>  select concat_ws(',','abc','def','gh')from tableName;
  5. abc,def,gh
    1. 字符串截取函数:substr,substring


  
  1. 语法: substr( string A,  int start),substring( string A,  int start)
  2. 返回值:  string
  3. 说明:返回字符串A从start位置到结尾的字符串
  4. hive>  select substr('abcde',3from tableName;
  5. cde
  6. hive>  select substring('abcde',3from tableName;
  7. cde
  8. hive>  select substr('abcde',-1from tableName; (和ORACLE相同)
  9. e
    1. 字符串截取函数:substr,substring


  
  1. 语法: substr( string A,  int start,  int len),substring( string A,  int start,  int len)
  2. 返回值:  string
  3. 说明:返回字符串A从start位置开始,长度为len的字符串
  4. hive>  select substr('abcde',3,2from tableName;
  5. cd
  6. hive>  select substring('abcde',3,2from tableName;
  7. cd
  8. hive> select substring('abcde',-2,2from tableName;
  9. de
    1. 字符串转大写函数:upper,ucase


  
  1. 语法: upper( string A) ucase( string A)
  2. 返回值:  string
  3. 说明:返回字符串A的大写格式
  4. hive>  select upper('abSEd'from tableName;
  5. ABSED
  6. hive>  select ucase('abSEd'from tableName;
  7. ABSED
    1. 字符串转小写函数:lower,lcase


  
  1. 语法: lower( string A) lcase( string A)
  2. 返回值:  string
  3. 说明:返回字符串A的小写格式
  4. hive>  select lower('abSEd'from tableName;
  5. absed
  6. hive>  select lcase('abSEd'from tableName;
  7. absed
    1. 去空格函数:trim


  
  1. 语法: trim( string A)
  2. 返回值:  string
  3. 说明:去除字符串两边的空格
  4. hive>  select trim(' abc 'from tableName;
  5. abc
    1. 左边去空格函数:ltrim


  
  1. 语法: ltrim( string A)
  2. 返回值:  string
  3. 说明:去除字符串左边的空格
  4. hive>  select ltrim(' abc 'from tableName;
  5. abc
    1. 右边去空格函数:rtrim


  
  1. 语法: rtrim( string A)
  2. 返回值:  string
  3. 说明:去除字符串右边的空格
  4. hive>  select rtrim(' abc 'from tableName;
  5. abc
    1. 正则表达式替换函数:regexp_replace


  
  1. 语法: regexp_replace( string A,  string B,  string C)
  2. 返回值:  string
  3. 说明:将字符串A中的符合java正则表达式B的部分替换为C。注意,在有些情况下要使用转义字符,类似oracle中的regexp_replace函数。
  4. hive>  select regexp_replace('foobar''oo|ar'''from tableName;
  5. fb
    1. 正则表达式解析函数:regexp_extract


  
  1. 语法: regexp_extract( string subject,  string pattern,  int index)
  2. 返回值:  string
  3. 说明:将字符串subject按照pattern正则表达式的规则拆分,返回index指定的字符。
  4. hive>  select regexp_extract('foothebar''foo(.*?)(bar)'1from tableName;
  5. the
  6. hive>  select regexp_extract('foothebar''foo(.*?)(bar)'2from tableName;
  7. bar
  8. hive>  select regexp_extract('foothebar''foo(.*?)(bar)'0from tableName;
  9. foothebar
  10. strong>注意,在有些情况下要使用转义字符,下面的等号要用双竖线转义,这是java正则表达式的规则。
  11. select data_field,
  12. regexp_extract(data_field, '.*?bgStart\\=([^&]+)', 1as aaa,
  13. regexp_extract(data_field, '.*?contentLoaded_headStart\\=([^&]+)', 1as bbb,
  14. regexp_extract(data_field, '.*?AppLoad2Req\\=([^&]+)', 1as ccc 
  15. from pt_nginx_loginlog_st 
  16. where pt =  '2021-03-28' limit  2;
    1. URL解析函数:parse_url


  
  1. 语法: parse_url( string urlString,  string partToExtract [,  string keyToExtract])
  2. 返回值:  string
  3. 说明:返回URL中指定的部分。partToExtract的有效值为:HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO.
  4. hive>  select parse_url
  5. ( 'https://www.tableName.com/path1/p.php?k1=v1&k2=v2#Ref1''HOST'
  6. from tableName;
  7. www.tableName.com 
  8. hive>  select parse_url
  9. ( 'https://www.tableName.com/path1/p.php?k1=v1&k2=v2#Ref1''QUERY''k1')
  10.   from tableName;
  11. v1
    1. json解析函数:get_json_object


  
  1. 语法: get_json_object(string json_string, string path)
  2. 返回值: string
  3. 说明:解析json的字符串json_string,返回path指定的内容。如果输入的json字符串无效,那么返回NULL。
  4. hive> select  get_json_object('{ "store":{ "fruit":\[{ "weight":8, "type": "apple"},{ "weight":9, "type": "pear"}],  "bicycle":{ "price":19.95, "color": "red"} }, "email": "amy@only_for_json_udf_test.net", "owner": "amy"}','$.owner') from tableName;
    1. 空格字符串函数:space


  
  1. 语法: space( int n)
  2. 返回值:  string
  3. 说明:返回长度为n的字符串
  4. hive>  select space(10from tableName;
  5. hive>  select length(space(10)) from tableName;
  6. 10
    1. 重复字符串函数:repeat


  
  1. 语法: repeat( string str,  int n)
  2. 返回值:  string
  3. 说明:返回重复n次后的str字符串
  4. hive>  select repeat('abc',5from tableName;
  5. abcabcabcabcabc
    1. 首字符ascii函数:ascii


  
  1. 语法: ascii( string str)
  2. 返回值:  int
  3. 说明:返回字符串str第一个字符的ascii码
  4. hive>  select ascii('abcde'from tableName;
  5. 97
    1. 左补足函数:lpad


  
  1. 语法: lpad( string str,  int  lenstring pad)
  2. 返回值:  string
  3. 说明:将str进行用pad进行左补足到 len
  4. hive>  select lpad( 'abc', 10, 'td') from tableName;
  5. tdtdtdtabc
  6. 注意:与GP,ORACLE不同,pad 不能默认
    1. 右补足函数:rpad


  
  1. 语法: rpad( string str,  int  lenstring pad)
  2. 返回值:  string
  3. 说明:将str进行用pad进行右补足到 len
  4. hive>  select rpad( 'abc', 10, 'td') from tableName;
  5. abctdtdtdt
    1. 分割字符串函数: split


  
  1. 语法: split( string str,  string pat)
  2. 返回值: array
  3. 说明: 按照pat字符串分割str,会返回分割后的字符串数组
  4. hive>  select split('abtcdtef','t'from tableName;
  5. [ "ab","cd","ef"]
    1. 集合查找函数: find_in_set


  
  1. 语法: find_in_set( string str,  string strList)
  2. 返回值:  int
  3. 说明: 返回str在strlist第一次出现的位置,strlist是用逗号分割的字符串。如果没有找该str字符,则返回 0
  4. hive>  select find_in_set('ab','ef,ab,de'from tableName;
  5. 2
  6. hive>  select find_in_set('at','ef,ab,de'from tableName;
  7. 0

复合类型构建操作

  • Map类型构建: map


  
  1. 语法: map (key1, value1, key2, value2, …)
  2. 说明:根据输入的key和 value对构建map类型
  3. hive>  Create table mapTable as select map('100','tom','200','mary'as t from tableName;
  4. hive> describe mapTable;
  5. t       map< string , string>
  6. hive>  select t  from tableName;
  7. { "100": "tom", "200": "mary"}
    1. Struct类型构建: struct


  
  1. 语法:  struct(val1, val2, val3, …)
  2. 说明:根据输入的参数构建结构体 struct类型
  3. hive>  create table struct_table as select struct('tom','mary','tim'as t from tableName;
  4. hive> describe struct_table;
  5. t        struct<col1: string ,col2: string,col3: string>
  6. hive>  select t  from tableName;
  7. { "col1": "tom", "col2": "mary", "col3": "tim"}
    1. array类型构建: array


  
  1. 语法:  array(val1, val2, …)
  2. 说明:根据输入的参数构建数组 array类型
  3. hive> create table arr_table  as select  array( "tom", "mary", "tim"as t  from tableName;
  4. hive> describe tableName;
  5. t        array< string>
  6. hive> select t  from tableName;
  7. [ "tom", "mary", "tim"]

复杂类型访问操作

    1. array类型访问: A[n]


  
  1. 语法: A[n]
  2. 操作类型: A为array类型,n为 int类型
  3. 说明:返回数组A中的第n个变量值。数组的起始下标为 0。比如,A是个值为[ 'foo''bar']的数组类型,那么A[ 0]将返回 'foo',而A[ 1]将返回 'bar'
  4. hive>  create table arr_table2 as select array("tom","mary","tim"as t
  5.   from tableName;
  6. hive>  select t[ 0],t[ 1from arr_table2;
  7. tom     mary    tim
    1. map类型访问: M[key]


  
  1. 语法: M[key]
  2. 操作类型: M为map类型,key为map中的key值
  3. 说明:返回map类型M中,key值为指定值的 value值。比如,M是值为{ 'f' ->  'foo''b' ->  'bar''all' ->  'foobar'}的map类型,那么M[ 'all']将会返回 'foobar'
  4. hive>  Create table map_table2 as select map('100','tom','200','mary'as t from tableName;
  5. hive>  select t[ '200'],t[ '100'from map_table2;
  6. mary    tom
    1. struct类型访问: S.x


  
  1. 语法: S.x
  2. 操作类型: S为 struct类型
  3. 说明:返回结构体S中的x字段。比如,对于结构体 struct foobar { int foo,  int bar},foobar.foo返回结构体中的foo字段
  4. hive>  create table str_table2 as select struct('tom','mary','tim'as t from tableName;
  5. hive> describe tableName;
  6. t        struct<col1: string ,col2: string,col3: string>
  7. hive>  select t.col1,t.col3  from str_table2;
  8. tom     tim

复杂类型长度统计函数

    1. Map类型长度函数: size(Map<k .V>)


  
  1. 语法: size(Map<k .V>)
  2. 返回值:  int
  3. 说明: 返回map类型的长度
  4. hive>  select size(tfrom map_table2;
  5. 2
    1. array类型长度函数: size(Array)


  
  1. 语法: size( Array<T>)
  2. 返回值:  int
  3. 说明: 返回 array类型的长度
  4. hive>  select size(t) from arr_table2;
  5. 4
    1. 类型转换函数 ***


  
  1. 类型转换函数: cast
  2. 语法: cast(expr  as <type>)
  3. 返回值: Expected  "=" to follow  "type"
  4. 说明: 返回转换后的数据类型
  5. hive>  select cast('1' as bigintfrom tableName;
  6. 1

hive当中的lateral view 与 explode以及reflect和窗口函数

使用explode函数将hive表中的Map和Array字段数据进行拆分

​ lateral view用于和split、explode等UDTF一起使用的,能将一行数据拆分成多行数据,在此基础上可以对拆分的数据进行聚合,lateral view首先为原始表的每行调用UDTF,UDTF会把一行拆分成一行或者多行,lateral view在把结果组合,产生一个支持别名表的虚拟表。

​ 其中explode还可以用于将hive一列中复杂的array或者map结构拆分成多行

需求:现在有数据格式如下


  
  1. zhangsan child 1,child 2,child 3,child 4 k 1:v 1,k 2:v 2
  2. lisi child 5,child 6,child 7,child 8 k 3:v 3,k 4:v 4

​ 字段之间使用\t分割,需求将所有的child进行拆开成为一列


  
  1. +----------+--+
  2. | mychild  |
  3. +----------+--+
  4. | child1   |
  5. | child2   |
  6. | child3   |
  7. | child4   |
  8. | child5   |
  9. | child6   |
  10. | child7   |
  11. | child8   |
  12. +----------+--+

​ 将map的key和value也进行拆开,成为如下结果


  
  1. +-----------+-------------+--+
  2. | mymapkey  | mymapvalue   |
  3. +-----------+-------------+--+
  4. | k1         | v1          |
  5. | k2        | v2           |
  6. | k3         | v3          |
  7. | k4        | v4           |
  8. +-----------+-------------+--+
    1. 创建hive数据库


  
  1. 创建hive数据库
  2. hive ( default)> create database hive_explode;
  3. hive ( default)>  use  hive_explode;
    1. 创建hive表,然后使用explode拆分map和array

hive (hive_explode)> create  table t3(name string,children array<string>,address Map<string,string>) row format delimited fields terminated by '\t'  collection items terminated by ',' map keys terminated by ':' stored as textFile;
    1. 加载数据


  
  1. node03执行以下命令创建表数据文件
  2.  mkdir -p  /export/servers /hivedatas/
  3.  cd  /export/servers /hivedatas/
  4.  vim maparray
  5. 内容如下:
  6. zhangsan child1,child2,child3,child4  k1:v1, k2:v2
  7. lisi child5,child6,child7,child8  k3:v3, k4:v4
  8. hive表当中加载数据
  9. hive (hive_explode)> load data local inpath  '/export/servers/hivedatas/maparray' into table t3;
    1. 使用explode将hive当中数据拆开


  
  1. array当中的数据拆分开
  2. hive (hive_explode)> SELECT explode(children)  AS myChild  FROM t3;
  3. 将map当中的数据拆分开
  4. hive (hive_explode)> SELECT explode(address)  AS (myMapKey, myMapValue)  FROM t3;

使用explode拆分json字符串

需求: 需求:现在有一些数据格式如下:

a:shandong,b:beijing,c:hebei|1,2,3,4,5,6,7,8,9|[{"source":"7fresh","monthSales":4900,"userCount":1900,"score":"9.9"},{"source":"jd","monthSales":2090,"userCount":78981,"score":"9.8"},{"source":"jdmart","monthSales":6987,"userCount":1600,"score":"9.0"}]

其中字段与字段之间的分隔符是 |

我们要解析得到所有的monthSales对应的值为以下这一列(行转列)

4900

2090

6987

    1. 创建hive表


  
  1. hive (hive_explode)> create table explode_lateral_view
  2.                    > ( `area`  string,
  3.                    >  `goods_id`  string,
  4.                    >  `sale_info`  string)
  5.                    > ROW FORMAT DELIMITED
  6.                    > FIELDS TERMINATED BY  '|'
  7.                    > STORED AS textfile;
    1. 准备数据并加载数据


  
  1. 准备数据如下
  2. cd  /export/servers/hivedatas
  3. vim explode_json
  4. a:shandong, b:beijing, c:hebei| 1, 2, 3, 4, 5, 6, 7, 8, 9|[{ "source": "7fresh", "monthSales": 4900, "userCount": 1900, "score": "9.9"},{ "source": "jd", "monthSales": 2090, "userCount": 78981, "score": "9.8"},{ "source": "jdmart", "monthSales": 6987, "userCount": 1600, "score": "9.0"}]
  5. 加载数据到hive表当中去
  6. hive (hive_explode)> load data local inpath  '/export/servers/hivedatas/explode_json' overwrite into table explode_lateral_view;
    1. 使用explode拆分Array

hive (hive_explode)> select explode(split(goods_id,',')) as goods_id from explode_lateral_view;
    1. 使用explode拆解Map

hive (hive_explode)> select explode(split(area,',')) as area from explode_lateral_view;
    1. 拆解json字段


  
  1. hive (hive_explode)> select explode(split(regexp_replace(regexp_replace(sale_info, '\\[\\{', ''), '}]', ''), '},\\{'))  as  sale_info  from explode_lateral_view;
  2. 然后我们想用get_json_object来获取key为monthSales的数据:
  3. hive (hive_explode)> select get_json_object(explode(split(regexp_replace(regexp_replace(sale_info, '\\[\\{', ''), '}]', ''), '},\\{')), '$.monthSales'as  sale_info  from explode_lateral_view;
  4. 然后挂了FAILED: SemanticException [ Error  10081]: UDTF 's are not supported outside the SELECT clause, nor nested in expressions
  5. UDTF explode不能写在别的函数内
  6. 如果你这么写,想查两个字段,select explode(split(area,', ')) as area,good_id from explode_lateral_view;
  7. 会报错FAILED: SemanticException 1:40 Only a single expression in the SELECT clause is supported with UDTF's.  Error encountered near token  'good_id'
  8. 使用UDTF的时候,只支持一个字段,这时候就需要LATERAL VIEW出场了

配合LATERAL VIEW使用

​ 配合lateral view查询多个字段


  
  1. hive (hive_explode)>  select goods_id2, sale_info from explode_lateral_view LATERAL VIEW explode(split(goods_id,','))goods as goods_id2;
  2. 其中 LATERAL VIEW explode(split(goods_id,','))goods相当于一个虚拟表,与原表explode_lateral_view笛卡尔积关联

​ 也可以多重使用


  
  1. hive (hive_explode)>  select goods_id2,sale_info, area2
  2.                     from explode_lateral_view 
  3.                     LATERAL VIEW explode(split(goods_id,','))goods as goods_id2 
  4.                     LATERAL VIEW explode(split(area,','))area as area2;也是三个表笛卡尔积的结果

最终,我们可以通过下面的句子,把这个json格式的一行数据,完全转换成二维表的方式展现

hive (hive_explode)> select get_json_object(concat('{',sale_info_1,'}'),'$.source'as source,get_json_object(concat('{',sale_info_1,'}'),'$.monthSales'as monthSales,get_json_object(concat('{',sale_info_1,'}'),'$.userCount'as monthSales,get_json_object(concat('{',sale_info_1,'}'),'$.score'as monthSales from explode_lateral_view LATERAL VIEW explode(split(regexp_replace(regexp_replace(sale_info,'\\[\\{',''),'}]',''),'},\\{'))sale_info as sale_info_1;

总结:

Lateral View通常和UDTF一起出现,为了解决UDTF不允许在select字段的问题。 Multiple Lateral View可以实现类似笛卡尔乘积。 Outer关键字可以把不输出的UDTF的空结果,输出成NULL,防止丢失数据。

行转列

相关参数说明:

​ CONCAT(string A/col, string B/col…):返回输入字符串连接后的结果,支持任意个输入字符串;

​ CONCAT_WS(separator, str1, str2,...):它是一个特殊形式的 CONCAT()。第一个参数剩余参数间的分隔符。分隔符可以是与剩余参数一样的字符串。如果分隔符是 NULL,返回值也将为 NULL。这个函数会跳过分隔符参数后的任何 NULL 和空字符串。分隔符将被加到被连接的字符串之间;

​ COLLECT_SET(col):函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段。

数据准备:

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

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


  
  1. 射手座,A            老王 |凤姐
  2. 白羊座,A            孙悟空|猪八戒
  3. 白羊座,B            宋宋

实现步骤:

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


  
  1. node03服务器执行以下命令创建文件,注意数据使用\t进行分割
  2. cd / export/servers/hivedatas
  3. vim constellation.txt
  4. 数据如下: 
  5. 孙悟空 白羊座 A
  6. 老王 射手座 A
  7. 宋宋 白羊座 B       
  8. 猪八戒 白羊座 A
  9. 凤姐 射手座 A
    1. 创建hive表并导入数据


  
  1. 创建hive表并加载数据
  2. hive (hive_explode)>  create  table person_info(
  3.                     name  string
  4.                     constellation  string
  5.                     blood_type  string
  6.                     row  format delimited fields terminated by  "\t";
  7.                     
  8. 加载数据
  9. hive (hive_explode)>  load data  local inpath  '/export/servers/hivedatas/constellation.txt' into  table person_info;
    1. 按需求查询数据


  
  1. hive (hive_explode)>  select
  2.                         t1. base,
  3.                         concat_ws( '|', collect_set(t1.name))  name
  4.                      from
  5.                         ( select
  6.                             name,
  7.                             concat(constellation, "," , blood_typebase
  8.                          from
  9.                             person_info) t1
  10.                      group  by
  11.                         t1. base;

列转行

所需函数:

​ EXPLODE(col):将hive一列中复杂的array或者map结构拆分成多行。

​ LATERAL VIEW

​ 用法:LATERAL VIEW udtf(expression) tableAlias AS columnAlias

​ 解释:用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合。

数据准备:


  
  1. cd / export/servers/hivedatas
  2. vim movie.txt
  3. 文件内容如下:  数据字段之间使用\t进行分割
  4. 《疑犯追踪》 悬疑,动作,科幻,剧情
  5. 《Lie  to me》 悬疑,警匪,动作,心理,剧情
  6. 《战狼 2》 战争,动作,灾难

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


  
  1. 《疑犯追踪》 悬疑
  2. 《疑犯追踪》 动作
  3. 《疑犯追踪》 科幻
  4. 《疑犯追踪》 剧情
  5. 《Lie  to  me》 悬疑
  6. 《Lie  to  me》 警匪
  7. 《Lie  to  me》 动作
  8. 《Lie  to  me》 心理
  9. 《Lie  to  me》 剧情
  10. 《战狼 2》 战争
  11. 《战狼 2》 动作
  12. 《战狼 2》 灾难

实现步骤:

    1. 创建hive表


  
  1. create  table movie_info(
  2.     movie  string
  3.      category  array< string>) 
  4. row  format  delimited  fields  terminated  by  "\t"
  5. collection items  terminated  by  ",";
    1. 加载数据

load data local inpath "/export/servers/hivedatas/movie.txt" into table movie_info;
    1. 按需求查询数据


  
  1. select
  2.     movie,
  3.     category_name
  4. from 
  5.     movie_info  lateral  view  explode( category) table_tmp  as category_name;

reflect函数

​ reflect函数可以支持在sql中调用java中的自带函数,秒杀一切udf函数。

需求1: 使用java.lang.Math当中的Max求两列中最大值

实现步骤:

    1. 创建hive表

create table test_udf(col1 int,col2 introw format delimited fields terminated by ',';
    1. 准备数据并加载数据


  
  1. cd  /export/servers/hivedatas
  2. vim  test_udf 
  3. 文件内容如下:
  4. 1 ,2
  5. 4 ,3
  6. 6 ,4
  7. 7 ,5
  8. 5 ,6
    1. 加载数据

hive (hive_explode)> load data local inpath '/export/servers/hivedatas/test_udf' overwrite into table test_udf;
    1. 使用java.lang.Math当中的Max求两列当中的最大值

hive (hive_explode)> select reflect("java.lang.Math","max",col1,col2from test_udf;

需求2: 文件中不同的记录来执行不同的java的内置函数

实现步骤:

    1. 创建hive表

hive (hive_explode)> create table test_udf2(class_name string,method_name string,col1 int , col2 int) row format delimited fields terminated by ',';
    1. 准备数据


  
  1. cd / export/servers/hivedatas
  2. vim test_udf2
  3. 文件内容如下:
  4. java.lang. Math,min, 1, 2
  5. java.lang. Math,max, 2, 3
    1. 加载数据

hive (hive_explode)> load data local inpath '/export/servers/hivedatas/test_udf2' overwrite into table test_udf2;
    1. 执行查询

hive (hive_explode)> select reflect(class_name,method_name,col1,col2) from test_udf2;

需求3: 判断是否为数字

实现方式:

​ 使用apache commons中的函数,commons下的jar已经包含在hadoop的classpath中,所以可以直接使用。

select reflect("org.apache.commons.lang.math.NumberUtils","isNumber","123")

窗口函数与分析函数

在sql中有一类函数叫做聚合函数,例如sum()、avg()、max()等等,这类函数可以将多行数据按照规则聚集为一行,一般来讲聚集后的行数是要少于聚集前的行数的。但是有时我们想要既显示聚集前的数据,又要显示聚集后的数据,这时我们便引入了窗口函数。窗口函数又叫OLAP函数/分析函数,窗口函数兼具分组和排序功能。

窗口函数最重要的关键字是 partition byorder by。

具体语法如下:over (partition by xxx order by xxx)

sum、avg、min、max

准备数据


  
  1. 建表语句:
  2. create  table test_t1(
  3. cookieid  string,
  4. createtime  string,    --day 
  5. pv  int
  6. row  format  delimited 
  7. fields  terminated  by  ',';
  8. 加载数据:
  9. load  data  local inpath  '/root/hivedata/test_t1.dat'  into  table test_t1;
  10. cookie1,2020-04-10,1
  11. cookie1,2020-04-11,5
  12. cookie1,2020-04-12,7
  13. cookie1,2020-04-13,3
  14. cookie1,2020-04-14,2
  15. cookie1,2020-04-15,4
  16. cookie1,2020-04-16,4
  17. 开启智能本地模式
  18. SET hive.exec.mode.local.auto= true;

SUM函数和窗口函数的配合使用:结果和ORDER BY相关,默认为升序。


  
  1. select cookieid,createtime,pv,
  2. sum(pv)  over( partition  by cookieid  order  by createtime)  as pv1 
  3. from test_t1;
  4. select cookieid,createtime,pv,
  5. sum(pv)  over( partition  by cookieid  order  by createtime  rows  between  unbounded  preceding  and  current  rowas pv2
  6. from test_t1;
  7. select cookieid,createtime,pv,
  8. sum(pv)  over( partition  by cookieid)  as pv3
  9. from test_t1;
  10. select cookieid,createtime,pv,
  11. sum(pv)  over( partition  by cookieid  order  by createtime  rows  between  3  preceding  and  current  rowas pv4
  12. from test_t1;
  13. select cookieid,createtime,pv,
  14. sum(pv)  over( partition  by cookieid  order  by createtime  rows  between  3  preceding  and  1  followingas pv5
  15. from test_t1;
  16. select cookieid,createtime,pv,
  17. sum(pv)  over( partition  by cookieid  order  by createtime  rows  between  current  row  and  unbounded  followingas pv6
  18. from test_t1;
  19. pv1: 分组内从起点到当前行的pv累积,如,11号的pv1=10号的pv+11号的pv, 12号=10号+11号+12号
  20. pv2: 同pv1
  21. pv3: 分组内(cookie1)所有的pv累加
  22. pv4: 分组内当前行+往前3行,如,11号=10号+11号, 12号=10号+11号+12号,
  23.                         13号=10号+11号+12号+13号, 14号=11号+12号+13号+14号
  24. pv5: 分组内当前行+往前3行+往后1行,如,14号=11号+12号+13号+14号+15号=5+7+3+2+4=21
  25. pv6: 分组内当前行+往后所有行,如,13号=13号+14号+15号+16号=3+2+4+4=13,
  26.         14号=14号+15号+16号=2+4+4=10

​ 如果不指定rows between,默认为从起点到当前行;

​ 如果不指定order by,则将分组内所有值累加;

​ 关键是理解rows between含义,也叫做window子句:

​ preceding:往前

​ following:往后

​ current row:当前行

​ unbounded:起点

​ unbounded preceding 表示从前面的起点

​ unbounded following:表示到后面的终点

​ AVG,MIN,MAX,和SUM用法一样。

row_number、rank、dense_rank、ntile

准备数据


  
  1. cookie1,2020-04-10,1
  2. cookie1,2020-04-11,5
  3. cookie1,2020-04-12,7
  4. cookie1,2020-04-13,3
  5. cookie1,2020-04-14,2
  6. cookie1,2020-04-15,4
  7. cookie1,2020-04-16,4
  8. cookie2,2020-04-10,2
  9. cookie2,2020-04-11,3
  10. cookie2,2020-04-12,5
  11. cookie2,2020-04-13,6
  12. cookie2,2020-04-14,3
  13. cookie2,2020-04-15,9
  14. cookie2,2020-04-16,7
  15.  
  16. CREATE  TABLE test_t2 (
  17. cookieid  string,
  18. createtime  string,    --day 
  19. pv  INT
  20. ROW  FORMAT  DELIMITED 
  21. FIELDS  TERMINATED  BY  ',' 
  22. stored  as textfile;
  23.   
  24. 加载数据:
  25. load  data  local inpath  '/root/hivedata/test_t2.dat'  into  table test_t2;
  • ROW_NUMBER()使用

    ROW_NUMBER()从1开始,按照顺序,生成分组内记录的序列。


  
  1. SELECT 
  2. cookieid,
  3. createtime,
  4. pv,
  5. ROW_NUMBER()  OVER( PARTITION  BY cookieid  ORDER  BY pv  descAS rn 
  6. FROM test_t2;
  • RANK 和 DENSE_RANK使用

    RANK() 生成数据项在分组中的排名,排名相等会在名次中留下空位 。

    DENSE_RANK()生成数据项在分组中的排名,排名相等会在名次中不会留下空位。


  
  1. SELECT 
  2. cookieid,
  3. createtime,
  4. pv,
  5. RANK()  OVER( PARTITION  BY cookieid  ORDER  BY pv  descAS rn1,
  6. DENSE_RANK()  OVER( PARTITION  BY cookieid  ORDER  BY pv  descAS rn2,
  7. ROW_NUMBER()  OVER( PARTITION  BY cookieid  ORDER  BY pv  DESCAS rn3 
  8. FROM test_t2 
  9. WHERE cookieid =  'cookie1';
  • NTILE

    有时会有这样的需求:如果数据排序后分为三部分,业务人员只关心其中的一部分,如何将这中间的三分之一数据拿出来呢?NTILE函数即可以满足。

    ntile可以看成是:把有序的数据集合平均分配到指定的数量(num)个桶中, 将桶号分配给每一行。如果不能平均分配,则优先分配较小编号的桶,并且各个桶中能放的行数最多相差1。

    然后可以根据桶号,选取前或后 n分之几的数据。数据会完整展示出来,只是给相应的数据打标签;具体要取几分之几的数据,需要再嵌套一层根据标签取出。


  
  1. SELECT 
  2. cookieid,
  3. createtime,
  4. pv,
  5. NTILE( 2OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS rn1,
  6. NTILE( 3OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS rn2,
  7. NTILE( 4OVER( ORDER  BY createtime)  AS rn3
  8. FROM test_t2 
  9. ORDER  BY cookieid,createtime;

其他一些窗口函数

lag,lead,first_value,last_value

  • LAG
    LAG(col,n,DEFAULT) 用于统计窗口内往上第n行值第一个参数为列名,第二个参数为往上第n行(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为NULL)


  
  1. SELECT cookieid,
  2. createtime,
  3. url,
  4. ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn,
  5. LAG(createtime, 1,' 1970- 01- 01  00: 00: 00') OVER(PARTITION BY cookieid ORDER BY createtime) AS last_ 1_time,
  6. LAG(createtime, 2) OVER(PARTITION BY cookieid ORDER BY createtime) AS last_ 2_time 
  7. FROM test_t 4;
  8. last_1_time: 指定了往上第 1行的值,default为' 1970- 01- 01  00: 00: 00'  
  9.                   cookie1第一行,往上 1行为NULL,因此取默认值  1970- 01- 01  00: 00: 00
  10.                   cookie1第三行,往上 1行值为第二行值, 2015- 04- 10  10: 00: 02
  11.                   cookie1第六行,往上 1行值为第五行值, 2015- 04- 10  10: 50: 01
  12. last_2_time: 指定了往上第 2行的值,为指定默认值
  13.           cookie1第一行,往上 2行为NULL
  14.           cookie1第二行,往上 2行为NULL
  15.           cookie1第四行,往上 2行为第二行值, 2015- 04- 10  10: 00: 02
  16.           cookie1第七行,往上 2行为第五行值, 2015- 04- 10  10: 50: 01
  • LEAD

与LAG相反 LEAD(col,n,DEFAULT) 用于统计窗口内往下第n行值 第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为NULL时候,取默认值,如不指定,则为NULL)


  
  1. SELECT cookieid,
  2. createtime,
  3. url,
  4. ROW_NUMBER()  OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS rn,
  5. LEAD(createtime, 1, '1970-01-01 00:00:00'OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS next_1_time,
  6. LEAD(createtime, 2OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS next_2_time 
  7. FROM test_t4;
  • FIRST_VALUE

    取分组内排序后,截止到当前行,第一个值


  
  1.   SELECT cookieid,
  2.  createtime,
  3.   url,
  4.  ROW_NUMBER()  OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS rn,
  5.   FIRST_VALUE( urlOVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS first1 
  6.   FROM test_t4;
  • LAST_VALUE

取分组内排序后,截止到当前行,最后一个值


  
  1. SELECT cookieid,
  2. createtime,
  3. url,
  4. ROW_NUMBER()  OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS rn,
  5. LAST_VALUE( urlOVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS last1 
  6. FROM test_t4;

如果想要取分组内排序后最后一个值,则需要变通一下:


  
  1. SELECT cookieid,
  2. createtime,
  3. url,
  4. ROW_NUMBER()  OVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS rn,
  5. LAST_VALUE( urlOVER( PARTITION  BY cookieid  ORDER  BY createtime)  AS last1,
  6. FIRST_VALUE( urlOVER( PARTITION  BY cookieid  ORDER  BY createtime  DESCAS last2 
  7. FROM test_t4 
  8. ORDER  BY cookieid,createtime;

特别注意order by

如果不指定ORDER BY,则进行排序混乱,会出现错误的结果


  
  1. SELECT cookieid,
  2. createtime,
  3. url,
  4. FIRST_VALUE( urlOVER( PARTITION  BY cookieid)  AS first2  
  5. FROM test_t4;

cume_dist,percent_rank

这两个序列分析函数不是很常用,注意: 序列函数不支持WINDOW子句

  • 数据准备


  
  1. d1,user1,1000
  2. d1,user2,2000
  3. d1,user3,3000
  4. d2,user4,4000
  5. d2,user5,5000
  6.  
  7. CREATE  EXTERNAL  TABLE test_t3 (
  8. dept  STRING,
  9. userid  string,
  10. sal  INT
  11. ROW  FORMAT  DELIMITED 
  12. FIELDS  TERMINATED  BY  ',' 
  13. stored  as textfile;
  14. 加载数据:
  15. load  data  local inpath  '/root/hivedata/test_t3.dat'  into  table test_t3;

  • CUME_DIST 和order byd的排序顺序有关系

    CUME_DIST 小于等于当前值的行数/分组内总行数 order 默认顺序 正序 升序 比如,统计小于等于当前薪水的人数,所占总人数的比例


  
  1.   SELECT 
  2.  dept,
  3.  userid,
  4.  sal,
  5.   CUME_DIST()  OVER( ORDER  BY sal)  AS rn1,
  6.   CUME_DIST()  OVER( PARTITION  BY dept  ORDER  BY sal)  AS rn2 
  7.   FROM test_t3;
  8.  
  9.  rn1: 没有partition,所有数据均为1组,总行数为5,
  10.       第一行:小于等于1000的行数为1,因此,1/5=0.2
  11.       第三行:小于等于3000的行数为3,因此,3/5=0.6
  12.  rn2: 按照部门分组,dpet=d1的行数为3,
  13.       第二行:小于等于2000的行数为2,因此,2/3=0.6666666666666666
  • PERCENT_RANK

    PERCENT_RANK 分组内当前行的RANK值-1/分组内总行数-1

    经调研 该函数显示现实意义不明朗 有待于继续考证


  
  1.    SELECT 
  2.   dept,
  3.   userid,
  4.   sal,
  5.    PERCENT_RANK()  OVER( ORDER  BY sal)  AS rn1,    --分组内
  6.    RANK()  OVER( ORDER  BY sal)  AS rn11,           --分组内RANK值
  7.    SUM( 1OVER( PARTITION  BY  NULLAS rn12,      --分组内总行数
  8.    PERCENT_RANK()  OVER( PARTITION  BY dept  ORDER  BY sal)  AS rn2 
  9.    FROM test_t3;
  10.   
  11.   rn1: rn1 = (rn11-1) / (rn12-1) 
  12.       第一行,(1-1)/(5-1)=0/4=0
  13.       第二行,(2-1)/(5-1)=1/4=0.25
  14.       第四行,(4-1)/(5-1)=3/4=0.75
  15.   rn2: 按照dept分组,
  16.        dept=d1的总行数为3
  17.        第一行,(1-1)/(3-1)=0
  18.        第三行,(3-1)/(3-1)=1

grouping sets,grouping__id,cube,rollup

​ 这几个分析函数通常用于OLAP中,不能累加,而且需要根据不同维度上钻和下钻的指标统计,比如,分小时、天、月的UV数。

  • 数据准备


  
  1. 2020-03,2020-03-10,cookie1
  2. 2020-03,2020-03-10,cookie5
  3. 2020-03,2020-03-12,cookie7
  4. 2020-04,2020-04-12,cookie3
  5. 2020-04,2020-04-13,cookie2
  6. 2020-04,2020-04-13,cookie4
  7. 2020-04,2020-04-16,cookie4
  8. 2020-03,2020-03-10,cookie2
  9. 2020-03,2020-03-10,cookie3
  10. 2020-04,2020-04-12,cookie5
  11. 2020-04,2020-04-13,cookie6
  12. 2020-04,2020-04-15,cookie3
  13. 2020-04,2020-04-15,cookie2
  14. 2020-04,2020-04-16,cookie1
  15.  
  16. CREATE  TABLE test_t5 (
  17. month  STRING,
  18. day  STRING
  19. cookieid  STRING 
  20. ROW  FORMAT  DELIMITED 
  21. FIELDS  TERMINATED  BY  ',' 
  22. stored  as textfile;
  23. 加载数据:
  24. load  data  local inpath  '/root/hivedata/test_t5.dat'  into  table test_t5;

  • GROUPING SETS

grouping sets是一种将多个group by 逻辑写在一个sql语句中的便利写法。

等价于将不同维度的GROUP BY结果集进行UNION ALL。

GROUPING__ID,表示结果属于哪一个分组集合。


  
  1. SELECT 
  2. month,
  3. day,
  4. COUNT( DISTINCT cookieid)  AS uv,
  5. GROUPING__ID 
  6. FROM test_t5 
  7. GROUP  BY  month, day 
  8. GROUPING  SETS ( month, day
  9. ORDER  BY GROUPING__ID;
  10. grouping_id表示这一组结果属于哪个分组集合,
  11. 根据grouping sets中的分组条件month,day,1是代表month,2是代表day
  12. 等价于 
  13. SELECT  month, NULL, COUNT( DISTINCT cookieid)  AS uv, 1  AS GROUPING__ID  FROM test_t5  GROUP  BY  month  UNION  ALL 
  14. SELECT  NULL  as  month, day, COUNT( DISTINCT cookieid)  AS uv, 2  AS GROUPING__ID  FROM test_t5  GROUP  BY  day;

再如:


  
  1. SELECT 
  2. month,
  3. day,
  4. COUNT( DISTINCT cookieid)  AS uv,
  5. GROUPING__ID 
  6. FROM test_t5 
  7. GROUP  BY  month, day 
  8. GROUPING  SETS ( month, day,( month, day)) 
  9. ORDER  BY GROUPING__ID;
  10. 等价于
  11. SELECT  month, NULL, COUNT( DISTINCT cookieid)  AS uv, 1  AS GROUPING__ID  FROM test_t5  GROUP  BY  month 
  12. UNION  ALL 
  13. SELECT  NULL, day, COUNT( DISTINCT cookieid)  AS uv, 2  AS GROUPING__ID  FROM test_t5  GROUP  BY  day
  14. UNION  ALL 
  15. SELECT  month, day, COUNT( DISTINCT cookieid)  AS uv, 3  AS GROUPING__ID  FROM test_t5  GROUP  BY  month, day;
  • CUBE

根据GROUP BY的维度的所有组合进行聚合。


  
  1. SELECT 
  2. month,
  3. day,
  4. COUNT( DISTINCT cookieid)  AS uv,
  5. GROUPING__ID 
  6. FROM test_t5 
  7. GROUP  BY  month, day 
  8. WITH  CUBE 
  9. ORDER  BY GROUPING__ID;
  10. 等价于
  11. SELECT  NULL, NULL, COUNT( DISTINCT cookieid)  AS uv, 0  AS GROUPING__ID  FROM test_t5
  12. UNION  ALL 
  13. SELECT  month, NULL, COUNT( DISTINCT cookieid)  AS uv, 1  AS GROUPING__ID  FROM test_t5  GROUP  BY  month 
  14. UNION  ALL 
  15. SELECT  NULL, day, COUNT( DISTINCT cookieid)  AS uv, 2  AS GROUPING__ID  FROM test_t5  GROUP  BY  day
  16. UNION  ALL 
  17. SELECT  month, day, COUNT( DISTINCT cookieid)  AS uv, 3  AS GROUPING__ID  FROM test_t5  GROUP  BY  month, day;
  • ROLLUP

是CUBE的子集,以最左侧的维度为主,从该维度进行层级聚合。


  
  1. 比如,以month维度进行层级聚合:
  2. SELECT 
  3. month,
  4. day,
  5. COUNT( DISTINCT cookieid)  AS uv,
  6. GROUPING__ID  
  7. FROM test_t5 
  8. GROUP  BY  month, day
  9. WITH  ROLLUP 
  10. ORDER  BY GROUPING__ID;
  11. --把month和day调换顺序,则以day维度进行层级聚合:
  12.  
  13. SELECT 
  14. day,
  15. month,
  16. COUNT( DISTINCT cookieid)  AS uv,
  17. GROUPING__ID  
  18. FROM test_t5 
  19. GROUP  BY  day, month 
  20. WITH  ROLLUP 
  21. ORDER  BY GROUPING__ID;
  22. (这里,根据天和月进行聚合,和根据天聚合结果一样,因为有父子关系,如果是其他维度组合的话,就会不一样)

微信搜索公众号【五分钟学大数据】 ,每周首发原创大数据技术文,深入框架原理,大厂面试真题等


转载:https://blog.csdn.net/helloHbulie/article/details/115376657
查看评论
* 以上用户言论只代表其个人观点,不代表本网站的观点或立场