函数较多,可以参考官方文档
LanguageManual UDF - Apache Hive - Apache Software Foundation
查看系统自带的函数
show functions;
显示自带的函数的用法
desc function round;
详细显示自带的函数的用法
desc function extended round;
取整函数: round
语法: round(double a) 返回值: BIGINT 说明:返回double类型的整数值部分(遵循四舍五入) -- 取整,结果:3 select round(3.1415926);
指定精度取整函数: round
语法: round(double a, int d) 返回值: DOUBLE 说明:返回指定精度d的double类型 -- 取整,精度为4,结果:3.1416 select round(3.1415926,4);
向下取整函数: floor
语法: floor(double a) 返回值: BIGINT 说明:返回等于或者小于该double变量的最大的整数 -- 向下取整,结果:3 select floor(3.1415926);
向上取整函数: ceil
语法: ceil(double a) 返回值: BIGINT 说明:返回等于或者大于该double变量的最小的整数 -- 向上取整,结果:4 select ceil(3.1415926);
获取随机数函数: rand
语法: rand(),rand(int seed) 返回值: double 说明:返回一个0到1范围内的随机数。如果指定种子seed,则会返回固定的随机数 -- 获取随机数,结果:0.5577432776034763 select rand(); -- 获取随机数,结果:0.6638336467363424 select rand(); -- 获取随机数,指定种子,结果:0.7220096548596434 select rand(100); -- 获取随机数,指定种子,结果:0.7220096548596434 select rand(100);
幂运算函数: pow
语法: pow(double a, double p) 返回值: double 说明:返回a的p次幂 -- 获取 2的4次方,结果:16.0 select pow(2,4) ;
绝对值函数: abs
语法: abs(double a) abs(int a) 返回值: double int 说明:返回数值a的绝对值 -- 获取绝对值,结果:3.9 select abs(-3.9); -- 获取绝对值,结果:10.9 select abs(10.9);
字符串长度函数:length
语法: length(string A) 返回值: int 说明:返回字符串A的长度 -- 返回字符串长度,结果:7 select length('abcedfg');
字符串反转函数:reverse
语法: reverse(string A) 返回值: string 说明:返回字符串A的反转结果 -- 字符串反转,结果:gfdecba select reverse('abcedfg');
字符串连接函数:concat
语法: concat(string A, string B…) 返回值: string 说明:返回输入字符串连接后的结果,支持任意个输入字符串 abcdefgh -- 字符串连接,结果:abcdefgh select concat('abc','def','gh');
字符串连接函数-带分隔符:concat_ws
语法: concat_ws(string SEP, string A, string B…) 返回值: string 说明:返回输入字符串连接后的结果,SEP表示各个字符串间的分隔符 -- 以 ',' 为分隔符,连接多个字符串,结果:abc,def,gh select concat_ws(',','abc','def','gh');
字符串截取函数:substr,substring
语法: substr(string A, int start),substring(string A, int start) 返回值: string 说明:返回字符串A从start位置到结尾的字符串 -- 起始位置为3截取,从1开始,包含起始位置,结果:cde select substr('abcde',3); -- 起始位置为3截取,从1开始,包含起始位置,结果:cde select substring('abcde',3); -- 从右往左,第一个位置为起始位置,结果:e select substr('abcde',-1);
字符串截取函数:substr,substring
语法: substr(string A, int start, int len),substring(string A, intstart, int len) 返回值: string 说明:返回字符串A从start位置开始,长度为len的字符串 -- 从左往右,起始位置为3,长度为2,结果:cd select substr('abcde',3,2); -- 从左往右,起始位置为3,长度为2,结果:cd hive> select substring('abcde',3,2); -- 从右往左,起始位置为2,长度为2,结果:de hive>select substring('abcde',-2,2);
字符串转大写函数:upper,ucase
语法: upper(string A) ucase(string A) 返回值: string 说明:返回字符串A的大写格式 -- 变大写,结果:ABSED select upper('abSEd'); -- 变大写,结果:ABSED select ucase('abSEd');
字符串转小写函数:lower,lcase
语法: lower(string A) lcase(string A) 返回值: string 说明:返回字符串A的小写格式 -- 变小写,结果:absed select lower('abSEd'); -- 变小写,结果:absed select lcase('abSEd');
去空格函数:trim
语法: trim(string A) 返回值: string 说明:去除字符串两边的空格 -- 去除空格,结果:abc select trim(' abc ');
左边去空格函数:ltrim
语法: ltrim(string A) 返回值: string 说明:去除字符串左边的空格 -- 去除左边空格,结果:'abc ' select ltrim(' abc ');
右边去空格函数:rtrim
语法: rtrim(string A) 返回值: string 说明:去除字符串右边的空格 -- 去除右边空格,结果:' abc' select rtrim(' abc ');
正则表达式替换函数:regexp_replace
语法: regexp_replace(string A, string B, string C) 返回值: string 说明:将字符串A中的符合java正则表达式B的部分替换为C。注意,在有些情况下要使用转义字符,类似oracle中的regexp_replace函数 -- 正则替换,结果:fb select regexp_replace('foobar', 'oo|ar', '');
URL解析函数:parse_url
语法: parse_url(string urlString, string partToExtract [, stringkeyToExtract]) 返回值: string 说明:返回URL中指定的部分。partToExtract的有效值为:HOST, PATH, QUERY, REF, PROTOCOL, AUTHORITY, FILE, and USERINFO. -- 获取 url 中的 host,结果:facebook.com select parse_url('http://facebook.com/path1/p.php?k1=v1&k2=v2#Ref1', 'HOST'); -- 获取 url 中的 path,结果:/path1/p.php select parse_url('http://facebook.com/path1/p.php?k1=v1&k2=v2#Ref1', 'PATH'); -- 获取 url 中的 参数,结果:v1 select parse_url('http://facebook.com/path1/p.php?k1=v1&k2=v2#Ref1', 'QUERY','k1');
分割字符串函数: split
语法: split(string str, stringpat) 返回值: array 说明:按照pat字符串分割str,会返回分割后的字符串数组 -- 字符串按照 't' 分割,结果:["ab","cd","ef"] select split('abtcdtef','t');
获取当前UNIX时间戳函数:unix_timestamp
语法: unix_timestamp() 返回值: bigint 说明:获得当前时区的UNIX时间戳 -- 获取当前的时间戳,结果:1323309615 select unix_timestamp();
UNIX时间戳转日期函数:from_unixtime
语法: from_unixtime(bigint unixtime[, string format]) 返回值: string 说明:转化UNIX时间戳(从1970-01-01 00:00:00 UTC到指定时间的秒数)到当前时区的时间格式 -- 按照指定格式格式化时间戳,结果:20111208 select from_unixtime(1323308943,'yyyyMMdd');
日期转UNIX时间戳函数:unix_timestamp
语法: unix_timestamp(string date) 返回值: bigint 说明:转换格式为"yyyy-MM-ddHH:mm:ss"的日期到UNIX时间戳。如果转化失败,则返回0。 -- 日期转换为时间戳,结果:1323234063 select unix_timestamp('2011-12-07 13:01:03');
指定格式日期转UNIX时间戳函数:unix_timestamp
语法: unix_timestamp(string date, string pattern) 返回值: bigint 说明:转换pattern格式的日期到UNIX时间戳。如果转化失败,则返回0。 -- 获取时间戳,结果:1323234063 select unix_timestamp('20111207 13:01:03','yyyyMMddHH:mm:ss');
日期时间转日期函数:to_date
语法: to_date(string timestamp) 返回值: string 说明:返回日期时间字段中的日期部分 -- 获取date,结果:2011-12-08 select to_date('2011-12-08 10:03:01');
日期转年函数: year
语法: year(string date) 返回值: int 说明:返回日期中的年 -- 获取年,结果:2011 select year('2011-12-08 10:03:01'); -- 获取年,结果:2012 hive> select year('2012-12-08');
日期转月函数: month
语法: month (string date) 返回值: int 说明:返回日期中的月份 -- 获取月,结果:12 select month('2011-12-08 10:03:01'); -- 获取月,结果:8 select month('2011-08-08');
日期转天函数: day
同样的,还有 hour,minute,second函数,分别是获取小时,分钟和秒,使用方式和以上类似,这里就不再讲述
语法: day (string date) 返回值: int 说明:返回日期中的天。 -- 获取天,结果:8 select day('2011-12-08 10:03:01'); -- 获取天,结果:24 select day('2011-12-24');
日期转周函数:weekofyear
语法: weekofyear (string date) 返回值: int 说明:返回日期在当前的周数 -- 获取周数,结果:49 select weekofyear('2011-12-08 10:03:01');
日期比较函数: datediff
语法: datediff(string enddate, string startdate) 返回值: int 说明:返回结束日期减去开始日期的天数。 -- 获取日期间的差值,结果:213 select datediff('2012-12-08','2012-05-09');
日期增加函数: date_add
语法: date_add(string startdate, int days) 返回值: string 说明:返回开始日期startdate增加days天后的日期 -- 获取增加10天后的日期,结果:2012-12-18 select date_add('2012-12-08',10);
日期减少函数: date_sub
语法: date_sub (string startdate, int days) 返回值: string 说明:返回开始日期startdate减少days天后的日期。 -- 获取减少10天后的日期,结果:2012-11-28 select date_sub('2012-12-08',10);
if函数: if
语法: if(boolean testCondition, T valueTrue, T valueFalseOrNull) 返回值: T 说明: 当条件testCondition为TRUE时,返回valueTrue;否则返回valueFalseOrNull -- 结果:200 select if(1=2,100,200) ; -- 结果:100 select if(1=1,100,200) ;
条件判断函数:CASE
语法: CASE a WHEN b THEN c [WHEN d THEN e]* [ELSE f] END 返回值: T 说明:如果a等于b,那么返回c;如果a等于d,那么返回e;否则返回f -- 结果:mary select case 100 when 50 then 'tom' when 100 then 'mary'else 'tim' end ; -- 结果:tim select case 200 when 50 then 'tom' when 100 then 'mary'else 'tim' end ;
条件判断函数:CASE
语法: CASE WHEN a THEN b [WHEN c THEN d]* [ELSE e] END 返回值: T 说明:如果a为TRUE,则返回b;如果c为TRUE,则返回d;否则返回e -- 结果:mary select case when 1=2 then 'tom' when 2=2 then 'mary' else'tim' end ; -- 结果:tom select case when 1=1 then 'tom' when 2=2 then 'mary' else'tim' end ;
cast()函数
公式:cast(表达式 as 数据类型) 返回值:转换成指定的数据类型 说明:cast函数,可以将"20190607"这样类型的时间数据转化成int类型数据。 -- 转换成日期类型,结果 select cast('2017-06-12' as date) filed;
行转列说明
① 行转列是指多行数据转换为一个列的字段。
② Hive 行转列用到的函数
--字段或字符串拼接 concat(str1,str2,...) --以分隔符拼接每个字符串 concat_ws(sep, str1,str2) --将某字段的值进行去重汇总,产生array类型字段 collect_set(col)
行转列测试数据
-- deptno(部门号),ename(员工姓名) 20,SMITH 30,ALLEN 30,WARD 20,JONES 30,MARTIN 30,BLAKE 10,CLARK 20,SCOTT 10,KING 30,TURNER 20,ADAMS 30,JAMES 20,FORD 10,MILLER
建表语句
create table emp( deptno int, ename string ) row format delimited fields terminated by ',';
插入数据
load data local inpath "/opt/software/emp.txt" into table emp;
开始转换
-- 函数只接受基本数据类型,它的主要作用是将某字段的值进行去重汇总,产生array类型字段 select deptno,concat_ws("|",collect_set(ename)) as ems from emp group by deptno;
表生成函数介绍
所有的表生成函数,包括自定义的和内置的,都被称为用户自定义表生成函数 (UDTF) 表生成函数,接受零个或多个输入,然后产生多列或多行输出
-- 将hive一列中复杂的array或者map结构拆分成多行。 explode(col) -- 列表中的每个元素生成一行 explode(ARRAY) -- map中每个key-value对,生成一行,key为一列,value为一列 explode(MAP)
数据准备
10,CLARK|KING|MILLER 20,SMITH|JONES|SCOTT|ADAMS|FORD 30,ALLEN|WARD|MARTIN|BLAKE|TURNER|JAMES
建表语句
create table emp1( deptno int, names array<string> ) row format delimited fields terminated by ',' collection items terminated by '|';
插入数据
load data local inpath "/opt/software/emp1.txt" into table emp1;
数据查询
select * from emp1; -- 将所有的员工姓名展示为行 select explode(names) as name from emp1;
LATERAL VIEW 函数介绍
-- 用法 LATERAL VIEW udtf(expression) tableAlias AS columnAlias -- 解释 用于和split, explode等UDTF一起使用,它能够将一列数据拆成多行数据,在此基础上可以对拆分后的数据进行聚合
列转行
select deptno,name from emp lateral view explode(names) tmp_tb as name;
Reflect 函数介绍
该函数可以支持在 sql
中调用 java
中的自带函数,即:UDF (User-Defined Function)用户自定义函数
案例一:使用 java.lang.Math
当中的Max求两列中最大值
① 建表语句
-- 创建hive表 create table test_udf(col1 int,col2 int) row format delimited fields terminated by ',';
② 准备数据
-- 准备数据 test_udf.txt 1,2 4,3 6,4 7,5 5,6
③ 加载数据
-- 加载数据 load data local inpath '/root/hivedata/test_udf.txt' into table test_udf;
④ 获取结果
-- 使用java.lang.Math当中的Max求两列当中的最大值 select reflect("java.lang.Math","max",col1,col2) from test_udf;
案例二:不同记录执行不同的 java
内置函数
① 建表语句
--创建hive表 create table test_udf2(class_name string,method_name string,col1 int , col2 int) row format delimited fields terminated by ',';
② 准备数据
-- 准备数据 test_udf2.txt java.lang.Math,min,1,2 java.lang.Math,max,2,3
③ 加载数据
-- 加载数据 load data local inpath '/opt/software/test_udf2.txt' into table test_udf2;
④ 获取结果
-- 执行查询 select reflect(class_name,method_name,col1,col2) from test_udf2;
函数的区别
函数 | 区别 |
---|---|
NTILE | |
ROW_NUMBER | 分区相同时,如果数据的排序相同,都会保留,数据依次递增/递减 |
RANK | 分区相同时,如果数据的排序相同,都会保留,但是会留下空位 |
DENSE_RANK | 分区相同时,如果数据的排序相同,都会保留,但是不会留下空位 |
数据准备
cookie1,2018-04-10,1 cookie1,2018-04-11,5 cookie1,2018-04-12,7 cookie1,2018-04-13,3 cookie1,2018-04-14,2 cookie1,2018-04-15,4 cookie1,2018-04-16,4 cookie2,2018-04-10,2 cookie2,2018-04-11,3 cookie2,2018-04-12,5 cookie2,2018-04-13,6 cookie2,2018-04-14,3 cookie2,2018-04-15,9 cookie2,2018-04-16,7
建表语句
CREATE TABLE net_his ( cookieid string, createtime string, --day pv INT ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' stored as textfile;
加载数据
-- 加载数据: load data local inpath '/opt/software/net_his.dat' into table net_his;
ROW_NUMBER 函数
-- ROW_NUMBER() 从1开始,按照顺序,生成分组内记录的序列 SELECT cookieid, createtime, pv, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn FROM net_his;
RANK 和 DENSE_RANK 函数
SELECT cookieid, createtime, pv, RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn1, DENSE_RANK() OVER(PARTITION BY cookieid ORDER BY pv desc) AS rn2, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY pv DESC) AS rn3 FROM net_his WHERE cookieid = 'cookie1';
数据准备
cookie1,2018-04-10,1 cookie1,2018-04-11,5 cookie1,2018-04-12,7 cookie1,2018-04-13,3 cookie1,2018-04-14,2 cookie1,2018-04-15,4 cookie1,2018-04-16,4
建表语句
--建表语句: create table net_his1( cookieid string, createtime string, --day pv int ) row format delimited fields terminated by ',';
加载数据
--加载数据: load data local inpath '/opt/software/net_his1.dat' into table net_his1;
开启智能本地模式
-- 本地模式:对数据量比较小的操作,就可以在本地执行,这样要比提交任务到集群执行效率要快很多 SET hive.exec.mode.local.auto=true;
SUM(结果和ORDER BY相关,默认为升序)
-- 如果不指定rows between,默认为从起点到当前行; -- 如果不指定order by,则将分组内所有值累加; -- 关键是理解rows between含义,也叫做window子句: -- preceding:往前 -- following:往后 -- current row:当前行 -- unbounded:起点 -- unbounded preceding 表示从前面的起点 -- unbounded following:表示到后面的终点 --pv1: 分组内从起点到当前行的pv累积,如,11号的pv1=10号的pv+11号的pv, 12号=10号+11号+12号 select cookieid,createtime,pv, sum(pv) over(partition by cookieid order by createtime) as pv1 from net_his1; --pv2: 同pv1 select cookieid,createtime,pv, sum(pv) over(partition by cookieid order by createtime rows between unbounded preceding and current row) as pv2 from net_his1;
--pv3: 分组内(cookie1)所有的pv累加 --如果每天 order by 排序语句,默认把分组内的所有数据进行sum操作 select cookieid,createtime,pv, sum(pv) over(partition by cookieid) as pv3 from net_his1;
--pv4: 分组内当前行+往前3行,如,11号=10号+11号, 12号=10号+11号+12号, 13号=10号+11号+12号+13号, 14号=11号+12号+13号+14号 select cookieid,createtime,pv, sum(pv) over(partition by cookieid order by createtime rows between 3 preceding and current row) as pv4 from net_his1;
--pv5: 分组内当前行+往前3行+往后1行,如,14号=11号+12号+13号+14号+15号=5+7+3+2+4=21 select cookieid,createtime,pv, sum(pv) over(partition by cookieid order by createtime rows between 3 preceding and 1 following) as pv5 from net_his1;
--pv6: 分组内当前行+往后所有行,如,13号=13号+14号+15号+16号=3+2+4+4=13, 14号=14号+15号+16号=2+4+4=10 select cookieid,createtime,pv, sum(pv) over(partition by cookieid order by createtime rows between current row and unbounded following) as pv6 from net_his1;
AVG,MIN,MAX 函数,和 SUM 用法相同
-- 计算到当前天的平均 pv 量 select cookieid,createtime,pv, avg(pv) over(partition by cookieid order by createtime rows between unbounded preceding and current row) as pv2 from net_his1;
-- 计算到当前天的最大 pv 量 select cookieid,createtime,pv, max(pv) over(partition by cookieid order by createtime rows between unbounded preceding and current row) as pv2 from net_his1;
-- 计算到当前天的最小 pv 量 select cookieid,createtime,pv, min(pv) over(partition by cookieid order by createtime rows between unbounded preceding and current row) as pv2 from net_his1;
注意: 如果不指定ORDER BY,则进行排序混乱,会出现错误的结果
数据准备
① 准备数据
cookie1,2018-04-10 10:00:02,url2 cookie1,2018-04-10 10:00:00,url1 cookie1,2018-04-10 10:03:04,1url3 cookie1,2018-04-10 10:50:05,url6 cookie1,2018-04-10 11:00:00,url7 cookie1,2018-04-10 10:10:00,url4 cookie1,2018-04-10 10:50:01,url5 cookie2,2018-04-10 10:00:02,url22 cookie2,2018-04-10 10:00:00,url11 cookie2,2018-04-10 10:03:04,1url33 cookie2,2018-04-10 10:50:05,url66 cookie2,2018-04-10 11:00:00,url77 cookie2,2018-04-10 10:10:00,url44 cookie2,2018-04-10 10:50:01,url55
② 建表语句
CREATE TABLE net_his2 ( cookieid string, createtime string, --页面访问时间 url STRING --被访问页面 ) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' stored as textfile;
③ 加载数据
--加载数据: load data local inpath '/opt/software/net_his2.dat' into table net_his2;
LAG 函数介绍
LAG( col,n,DEFAULT )
用于统计窗口内往上 第n行
值第一个参数为列名,第二个参数为往上 第n行
(可选,默认为1),第三个参数为默认值(当往上第n行为NULL时候,取默认值,如不指定,则为 NULL)
--last_1_time: 指定了往上第1行的值,default为'1970-01-01 00:00:00' cookie1第一行,往上1行为NULL,因此取默认值 1970-01-01 00:00:00 cookie1第三行,往上1行值为第二行值,2015-04-10 10:00:02 cookie1第六行,往上1行值为第五行值,2015-04-10 10:50:01 --last_2_time: 指定了往上第2行的值,为指定默认值 cookie1第一行,往上2行为NULL cookie1第二行,往上2行为NULL cookie1第四行,往上2行为第二行值,2015-04-10 10:00:02 cookie1第七行,往上2行为第五行值,2015-04-10 10:50:01 SELECT cookieid, createtime, url, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, LAG(createtime,1,'1970-01-01 00:00:00') OVER(PARTITION BY cookieid ORDER BY createtime) AS last_1_time, LAG(createtime,2) OVER(PARTITION BY cookieid ORDER BY createtime) AS last_2_time FROM net_his2;
LEAD 函数介绍
与 LAG
相反 LEAD(col,n,DEFAULT)
用于统计窗口内往下第n行值第一个参数为列名,第二个参数为往下第n行(可选,默认为1),第三个参数为默认值(当往下第n行为 NULL
时候,取默认值,如不指定,则为 NULL
)
SELECT cookieid, createtime, url, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, LEAD(createtime,1,'1970-01-01 00:00:00') OVER(PARTITION BY cookieid ORDER BY createtime) AS next_1_time, LEAD(createtime,2) OVER(PARTITION BY cookieid ORDER BY createtime) AS next_2_time FROM net_his2;
FIRST_VALUE 函数
取分组内排序后,截止到当前行,第一个值
SELECT cookieid, createtime, url, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, FIRST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS first1 FROM net_his2;
LAST_VALUE 函数
-- 取分组内排序后,截止到当前行,最后一个值 SELECT cookieid, createtime, url, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, LAST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS last1 FROM net_his2; -- 如果想要取分组内排序后最后一个值,则需要变通一下 SELECT cookieid, createtime, url, ROW_NUMBER() OVER(PARTITION BY cookieid ORDER BY createtime) AS rn, LAST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime) AS last1, FIRST_VALUE(url) OVER(PARTITION BY cookieid ORDER BY createtime DESC) AS last2 FROM net_his2 ORDER BY cookieid,createtime;