Hive Sql的日常使用笔记
1. distinct 和 group by
distinct 只能返回去重的列
group by 理论上是需要在 select 后面配合聚合函数(sum, avg, max, min, count)来使用的
select 后面没有在聚合函数中的列都需要写在 group by 的后面,eg:
1 | select A1, A2, A3, max(B) from test group by A1, A2, A3 |
select distinct(A), B from test
和 select distinct A, B from test
返回的是一样的,返回的都是 A 和 B 的组合值没有重复的结果
如果需要去重的话,select 需要的列 from A, (select min(主键) from A group by 要去重的列)B where A.主键 = B.主键
2. left join
A left join B on A.a1 = B.b and A.a2 = 'val'
保留 A 的所有结果,同时 on 后面的结果只针对这一条 left join 语句,不会影响最后的筛选,所以如果要保留所有 A.a2 = ‘val’ 的数据的话,应该在最后写 where A.a2 = 'val'
3. if 和 case when
一层: if(A.a = 'key', val1, val2)
两层: if(A.a = 'key1', val1, if(A.a = 'key2', val2, val3))
1 | case A.a |
4. regexp_replace
替换掉 A.a 字段中的点 regexp_replace(A.a, "\\.", "")
5. cast
cast(A.a as int)
6. concat
concat(A.a,'-01-01')
7. concat_ws 行转列
concat_ws('/', collect_set(label_name))label_name group by key
concat 会自动把参数转换为字符串进行拼接,但是 concat_ws 需要提前将数值 cast 成字符串
8. regexp
where trim(A.a) regexp '^[1-9 | A-E]'
9. from_unixtime
from_unixtime(unix_timestamp(),'yyyy-MM-dd hh:mm:ss') update_time
10. 索引
索引基数: 数据列所包含的不同值的数量。索引的基数相对于数据表行数较高(即列中包含很多不同的值,重复的值很少),这个时候创建的索引效果更好。因为查询优化器如果发现某个值出现在表的数据行中的百分比很高的时候,可能会忽略索引直接进行全盘扫描。
11. row_number()
row_number() over(partition by 主键 order by 字段1 desc)as r
12.多个条件
if(boolean, res1, if(boolean, res2, if(boolean, res3,……)))
13.nvl
nvl(a,b)
如果a为null 那就取b 只能判断null 不能判断空
14.decimal
1 | cast(round((sum(an) * 100 / sum(tn)),2) as decimal(20,2)) |
15.补零
1 | if(substr(bp, 1, 1) != 'X' and bp is not null and trim(bp) != 'null' and trim(bp) != '' and trim(bp) != '*', lpad(bp, 10, '0'), bp)as temp |
16.推数编码出错
1 | Incorrect string value: '\xF0\xAF\xA0\xA5' for column 'customer_txt' at row 45 |
以下几种方法有可能可以解决:
- 修改字符集为 utf8mb4
--default-character-set gbk
在 sqoop 最后转换为 gbk 编码- 出错原因是
can't parse data ' '
之类的话,可能是因为特殊字符,需要一个个排查,可以试一下regexp_replace(field,'\0','')
17.去重
1 | select distinct t1.objnr |
18.插入数据
1 | insert into table values ('05:00','6') ,('06:00','7'), |
19.每隔N小时取数分组求和
通过截取字符串,获取时间,除以N保留整数位,分组
20.正则表达式的匹配
1 | select regexp_replace('[3]','[','a') 不识别 |
21.空字符串关联
- (NULL) 在 join on 的时候不会被关联出来
- ‘’ ‘ ‘ 在 join on 的时候会相互关联,只要有匹配项就会关联出来
- (NULL) 只在 left jion 的时候可以出来
22.lateral view explode 列转行
1 | select gid, assist |
23. userids 包含 gid
1 | find_in_set(gid, userids) # userids 需要用逗号分隔 |
24.pmod(a, b) 取模(取余)运算
1 | pmod(7, 4) -> 3 |
25.insert 和 insert overwrite
insert overwrite 本质是先覆盖原先的表,再把新的数据插入
26.insert 和 insert into
1 | insert table user(id, name) values(1, 'zhangsan'); |
27.max(if) 或者 max(case when) 行转列
1 | select id, |
28.复制表结构 但不复制数据
create table Test2 like Test1;
29.两个限制条件
要让每一条数据都满足 balance < 0,gas > 0,转换成 count(if(balance >= 0, 1, 0)) as a, count(if(gas <= 0, 1, 0)) as b,然后 where 中取 a = 0 and b = 0 的数据
30.join优化
- 多表join,其中有一个是最大的表
1 | select /*+ STREAMTABLE(table1) */ tabl1.a, table1.b, table2.c |
hive会假定查询中最后一个表是最大的表。在对每行记录进行连接操作的时候,会尝试将其他表缓存起来,然后扫描最后那个表进行计算。通过
/*+ STREAMTABLE(table1) */
可以显式地指出最大的表是哪一个,hive会将其作为驱动表,哪怕它不是在 join 的最后面
- 多表join,其中有一个是最小的表
1 | select /*+ MAPJOIN(table1) */ tabl1.a, table1.b, table2.c |
如果所有表中只有一张表是小表,那么可以在最大的表通过mapper的时候将小表完全放到内存中。Hive可以在map端执行连接过程(称为map-side JOIN),这是因为hive可以和内存中的小表进行逐一匹配,从而省略掉常规连接操作所需要的reduce过程。
31.导出mysql数据库的注释
1 | SELECT |
32. count()
count(*):所有行进行统计,包括NULL行
count(1):所有行进行统计,包括NULL行
count(column):统计column所有非NULL行
33. sum(if…) 和 count(if…)
在计数的时候,以下两种方式是等效的:
1 | sum(if(条件判断, 1, 0)) |
原因在于 NULL 并不参加任何计算(但是升序排序的时候 NULL 是第一个,因为ASC码最小)。
34. sum() over(…)
1 | sum() over(partition by year) 计算结果是按照 year 分组来 sum 的总和 |
同理适用于其他的窗口函数
35. count(distinct a) 不支持窗口函数,即不支持后面跟着 over(partiton by 1)
36. size 函数 返回后面map或者array里面的元素个数
1 | size(collect_set(字段)) over(partiton by 1) |
37. 设置变量
1 | set myvar = "test"; |
38. coalesce() 函数
依次查看每一个表达式,返回第一个非空值,如果都是空,最后返回空值
coalesce(expression_1, expression_2, ...,expression_n)
39. count(distinct) 优化
直接使用 count(distinct) 会把数据放入到一个 reducer 下进行计算,导致运行缓慢。
比如统计本月活跃用户个数
优化一:
1 | -- 外层SELECT求和 |
这里 uuid 只截取了3位,如果截取位数过多,假设 uuid 长度为30位,内层 group by 会产生 30^n 个分组,那么外层也需要进行 30^n 次求和
优化二:
1 | -- 第三层SELECT |
如果数据量确实很大,也可以增加分组的个数。例如:CAST(RAND() * 1000 AS BIGINT) tag