一、基本数据类型
tinyint 1byte 有符号整数
smallint 2byte 有符号整数
int 4byte 有符号整数
bigint 8byte 有符号整数
boolean 布尔类型,true或者false
float 单精度浮点数
double 双精度浮点数
decimal 十进制精准数字类型 decimal(16,2)
varchar 字符序列,需指定最大长度,最大长度的范围是[1,65535] varchar(32)
string 字符串,无需指定最大长度
timestamp 时间类型
binary 二进制数据
array 数组是一组相同类型的值的集合 array arr[0]
map map是一组相同类型的键-值对集合 map<string, int> map[‘key’]
struct 结构体由多个属性组成,每个属性都有自己的属性名和数据类型 struct<id:int, name:string> struct.id
二、基本查询
Home - Apache Hive - Apache Software Foundation
1、语法:
SELECT [ALL | DISTINCT] select_expr, select_expr, …
FROM table_reference – 从什么表查
[WHERE where_condition] – 过滤
[GROUP BY col_list] – 分组查询
[HAVING col_list] – 分组后过滤
[ORDER BY col_list] – 排序 -- 全局排序
[CLUSTER BY col_list -- 分区排序(当 distribute by 和 sort by 字段相同时,可以使用 cluster by方式。)
| [DISTRIBUTE BY col_list] [SORT BY col_list]
]
[LIMIT number] – 限制输出的行数
2、join连接
左右关联:inner、outer均可省略
内连接(join或inner join):只有2个表中连接字段都匹配的数据才会被保留。
左外连接(left join或left outer join):保留左表记录,右边不符合条件的用null填充
右外连接(right join或right outer join)
满外连接(full join或full outer join):保留两边全部,任一表没有符合条件的用null填充
左半连接(left semi join):内连接后,仅返回左表剩余的数据
交叉连接(笛卡尔积cross join):所有表中的所有行互相连接。
3、union和union all上下拼接:
union和union all在上下拼接sql结果时有两个要求:
(1)两个sql的结果,列的个数必须相同
(2)两个sql的结果,上下所对应列的类型必须一致
union去重并对结果排序,union all不去重
4、排序
(1)全局排序(Order By)
全局排序,只有一个Reduce。asc(ascend):升序(默认)desc(descend):降序
通常和limit一起使用,可以让每个map只需要处理limit的个数数据
(2)每个Reduce内部排序(Sort By)
Sort by为每个reduce产生一个排序文件。每个Reduce内部进行排序,对全局结果集来说不是排序。
(3)分区(Distribute By)
distribute by类似MapReduce中partition(自定义分区),进行分区,结合sort by使用。
分区排序(Cluster By)
(4)当distribute by和sort by字段相同时,可以使用cluster by方式。cluster by除了具有distribute by的功能外还兼具sort by的功能。但是排序只能是升序排序。
三、常用函数
1、单行函数
输入一行,输出一行
-
round:四舍五入
-
ceil:向上取整
-
floor:向下取整
-
if(condition, trueValue, falseValue)
-
case when:case when a then b [when c then d]* [else e] end :条件判断函数;如果a为true,则返回b;如果c为true,则返回d;否则返回 e ;针对同一个字段的等值判断可以把字段提在case后面
-
cast(stuId AS INT) :类型转换
-
nvl(A,B) :替换null值 ;A的值不为null,则返回A,否则返回B
-
substring:截取字符串substring(string A, int start, int len)
-
replace :替换 ;replace(string A, string B, string C) 字符串A中的子字符串B替换为C。
-
regexp_replace:正则替换 ;regexp_replace(string A, string B, string C) 将字符串A中的符合java正则表达式B的部分替换为C。
-
regexp:正则匹配;select ‘dfsaaaa’ regexp ‘dfsa+’,正则匹配成功,输出true
-
repeat:重复字符串;repeat(string A, int n),字符串A重复n遍
-
split(string str, string pat) :将一个字符串根据指定的分隔符进行分割,并返回一个数组。eg:split(arr,','),split(arr,'\\')[0]。当逗号作为分隔符时,保持不变,其他多数时候要加转义,如split(properties,'\_')
-
concat(string A, string B, string C, ……) 将A,B,C……等字符拼接为一个字符串
-
concat_ws(分隔符, string…| array(string)): 指定分隔符拼接字符串或者字符串数
-
get_json_object(string json_string, string path) 解析json的字符串json_string,返回path指定的内容。如果输入的json字符串无效,那么返回NULL。select get_json_object(‘[{“name”:“大海海”,“sex”:“男”,“age”:“25”},{“name”:“小宋宋”,“sex”:“男”,“age”:“47”}]’,‘$.[0].name’);
-
unix_timestamp:返回当前或指定时间的时间戳;例如:
select unix_timestamp(‘2022/08/08 08-08-08’,‘yyyy/MM/dd HH-mm-ss’);
from_unixtime(bigint unixtime[, string format]) 转化UNIX时间戳到当前时区的时间格式 -
select current_date:-- 获取当前日期,格式:2022-09-13
-
date_format(date,格式) -- 如:date_format('2022-09-13 12:00:00', 'yyyy-MM-dd')
-
current_timestamp:-- 获取当前时间戳。 2022-09-13 17:52:57.613
-
fom_unixtime(bigint unixtime[, string format]); -- 把UNIX 时间戳(从1970-01-01 00:00:00 UTC 到指定时间的秒数)转为时间或者指定格式日期。
-
unix_timestamp(time) -- 把yyyy-MM-dd HH:mm:ss转为unix时间戳
-
to_date(time) -- 转为日期格式,默认为yyyy-MM-dd格式。
-
datediff:两个日期相差的天数(结束日期减去开始日期的天数)
-
date_add(string startdate, int days) :日期加天数
-
date_sub (string startdate, int days) 日期减天数
-
year(date) -- 获取年份
-
month(date) -- 获取月份
-
day(date) -- 获取日
-
hour(date) -- 获取小时
-
minute(date) -- 获取分钟
-
second(date) -- 获取秒
-
last_day(date) -- 指定日期所在月份的最后一天
-
weekofyear(date) --返回日期在该年的周数
-
-- 判断周几
select
case when dayofweek('${etl_date}') =1 then '星期日'
when dayofweek('${etl_date}') =7 then '星期六'
when dayofweek('${etl_date}') =6 then '星期五'
when dayofweek('${etl_date}') =5 then '星期四'
when dayofweek('${etl_date}') =4 then '星期三'
when dayofweek('${etl_date}') =3 then '星期二'
when dayofweek('${etl_date}') =2 then '星期一'
else null
end as weekday
-
map (key1, value1, key2, value2, …) 根据输入的key和value对构建map类型
-
map_keys: 返回map中的key;map_values: 返回map中的value;
select map_keys(map(‘xiaohai’,1,‘dahai’,2)); -
array(val1, val2, …) 根据输入的参数构建数组array类
-
array_contains: 判断array中是否包含某个元素 ;select array_contains(array(‘a’,‘b’,‘c’,‘d’),‘a’);
-
sort_array:将array中的元素排序
-
struct(val1, val2, val3, …) 根据输入的参数构建结构体struct类
2、高级聚合函数
多进一出 (多行传入,一个行输出)。
- 普通聚合 count/sum.
-
collect_set():多行数据收集为一行,返回set集合,无序不重复
-
collect_list():多行数据收集为一行,返回list集合,有序重复
3、炸裂函数UDTF(制表函数)
接收一行,输出多行。
常用的UDTF ----explode(array as 字段名)
常用的UDTF ----explode(map as (key,value))
常用的UDTF ----poseexplode(array as 字段名) 会返回位置,索引
常用的UDTF ----inline(array<STRUCTf1:T1,....fn,Tn> as 字段名)
Latera View:通常与UDTF配合使用。Lateral View可以将UDTF应用到源表的每行数据,将每行数据转换为一行或多行,并将源表中每行的输出结果与该行连接起来,形成一个虚拟表。
eg:
select col1, col2, tmp_table.tmp_col
from test_tb
lateral view explode(split(col3, '分隔符')) tmp_table as tmp_col
where partition_name='xxx'
-- create table if not exists tb
-- (
-- class string comment '班级名称',
-- student string comment '学生名称',
-- score string comment '学生分数'
--)
-- comment '学生成绩表';
--INSERT overwrite table tb
--VALUES ("1班","小A,小B,小C","80,92,70"),
-- ("2班","小D,小E","88,62"),
-- ("3班","小F,小G,小H","90,97,85");
select class, student, score,
stu_name, stu_score
from tb
lateral view posexplode(split(student, ',')) tmp3 as stu_index1, stu_name
lateral view posexplode(split(score, ',')) tmp4 as stu_index2, stu_score
where stu_index1 = stu_index2;
-- tmp_table:explode形成的新虚拟表,可以不写;
-- tmp_col:explode 形成的新列(字段)
4、窗口函数
窗口函数,function(arg):对应的窗口数据计算函数
function(arg) over (partition by {分区列名} order by {order 列名} desc|asc [rows|range between 起点行 and 终点行])
(1)常用窗口-窗口计算
1)sum(col) over ()
2)avg(col) over ()
3)max(col) over ()
4)min(col) over ()
5)count(col) over ()
6)cume_dist() over (order by col)
--如果按升序排列,则统计:小于等于当前值的行数/总行数(number of rows ≤ current row)/(total number ofrows)。
--如果是降序排列,则统计:大于等于当前值的行数/总行数
eg: cume_dist() over (ORDER BY salary) as cume_dist -- 统计小于等于当前工资的人数占总人数的比例
cume_dist() over (PARTITION BY dept_no ORDER BY salary) as cume_dist -- 根据部门统计小于等于当前工资的人数占部门总人数的比例
(2)常用窗口-跨行取值函数
1)first_value(col) over ():首行值
2)last_value(col) over ():末行值
lag和lead:获取当前行的上、下某行、某个字段的值;不支持自定义窗口范围。
3) lag(col,n,defaultValue) over(partion by..order by..):查询字段col,当前行往前数第n行的数据,若为null显示默认值defaultValue;
lag(col):指默认每次取字段col当前行的上一行数据
lag(col, n) over ():取窗口范围往前第 n 行数据的值
4) lead(col, n,defaultValue) over ():取窗口范围往后第 n 行数据的值
5) ntile(n) over(partition by col1 order by col2):col1为分组的列名,col2为排序的列名,将有序分组的窗口范围,平均分成n份,每一份编号依次为1、2、3...、n;如果要取其中第m份,需要用到嵌套子查询
(3)常用窗口-排名函数
row_number() over (partition by col1 order by col2) as row_number
-- 连续排序。在窗口内会对所有数值,每个组输出的序号唯一且连续,如:1、2、3、4、5。
rank() over (partition by col1 order by col2) as rank
-- 相同数值,输出相同的序号,而且下一个序号间断,如:1、1、3、3、5。
dense_rank() over (partition by col1 order by col2) as rank
-- 相同数值,输出相同的序号,但下一个序号不间断,如:1、1、2、2、3。
percent_rank() over():返回order by列的百分比排名
四、导入导出文件
1、load将文件导入hive表中
语法:LOAD DATA [LOCAL] INPATH ‘filepath’ [OVERWRITE] INTO TABLE tablename [PARTITION (partcol1=val1, partcol2=val2 …)];
(1)local:表示从本地加载数据到Hive表;否则从HDFS加载数据到Hive表。(如果是本地数据则是复制一份到hive路径,如果是HDFS则是移动到hive路径)
(2)overwrite:表示覆盖表中已有数据,否则表示追加。
(3)partition:表示上传到指定分区,若目标是分区表,需指定分区。
eg:load data local inpath ‘/opt/module/hive/datas/dept_20220401.log’
into table dept_partition partition(day=‘20220401’);
2、将hive查询导出到本地文件
INSERT OVERWRITE LOCAL DIRECTORY '/path/to/local/directory'
ROW FORMAT DELIMITED
FIELDS TERMINATED BY ','
LINES TERMINATED BY '\n'
SELECT * FROM your_hive_table;
五、sql使用
1、随机抽样
-- 随机抽样
use dmr_dev;
create table if not exists feature_train_202009 as
(
select uid, req_dt, flag, req_month, feature_libsvm
from tb
where req_dt='2020-09-28'
order by rand()
limit 10000
);
-- 随机抽样
select *
from tb
TABLESAMPLE(10 ROWS);
-- 随机抽样(百分比)
select *
from tb
TABLESAMPLE(10 PERCENT);
2、hive窗口函数去重
use dmr_dev;
set hive.support.quoted.identifiers=none;
create table if not exists dmr_dev.bussiness_pinkey_all_feature as
(
select (num)?+.+
from
(
select row_number() over (partition by req_dt, uid order by req_dt, uid asc) num, *
from dmr_dev.all_bussiness_pinkey_all_feature
) t
where t.num=1
);
3、求分位数
-- 分位数
use dmr_dev;
drop table if exists dmr_dev.dmrc_model_anti_fraud_outer_tx_if_result_i_m_array;
create table if not exists dmr_dev.dmrc_model_anti_fraud_outer_tx_if_result_i_m_array as
select
percentile_approx(predict_score,array(0.25,0.5,0.75,0.9,0.95)) as predict_score_arr
from (select a.*
from
(
select *
from dmr_c.dmrc_model_anti_fraud_outer_tx_if_result_i_m
where dt = '2021-10-01'
) a
join (select count(1) as cnt
from dmr_c.dmrc_model_anti_fraud_outer_tx_if_result_i_m
where dt = '2021-10-01'
) b
where rand(123) < 100000/cnt
) tmp;
-- 省略ON条件,Hive将尝试进行笛卡尔积(Cartesian product),即将第一个表的每一行与第二个表的每一行组合
4、模型打分分箱,效果分析
-- 基于3求分位数后,模型打分分箱
-- (,arr[0]] 1
-- (arr[0], arr[1]] 2
-- (arr[1], arr[2]] 3
-- (arr[2], arr[3]] 4
-- (arr[3], arr[4]] 5
-- (arr[4], ) 6
CREATE TEMPORARY MACRO score_grp(x double,arr array<double>)
case when x<=arr[0] then 1
when x<=arr[1] then 2
when x<=arr[2] then 3
when x<=arr[3] then 4
when x<=arr[4] then 5
when x>arr[4] then 6 end;
use dmr_dev;
drop table if exists dmr_dev.dmrc_model_anti_fraud_outer_tx_if_result_i_m_score;
create table if not exists dmr_dev.dmrc_model_anti_fraud_outer_tx_if_result_i_m_score as
select a.*,
score_grp(a.predict_score, b.predict_score_arr) as predict_score_grp
from
( select *
from dmr_c.dmrc_model_anti_fraud_outer_tx_if_result_i_m
where dt = '2021-10-01'
) a
left join dmr_dev.dmrc_model_anti_fraud_outer_tx_if_result_i_m_array b;
-- 此处省略on条件
-- 模型效果分析
select predict_score_grp, count(1) as cnt
from dmr_dev.dmrc_model_anti_fraud_outer_tx_if_result_i_m_score
group by predict_score_grp
order by predict_score_grp;