这里单独说一下跟数据研发相关的sql知识,首先不管是hadoop,spark,flink都是有Sql Api的,是什么意思呢?就是说不管hadoop底层怎么map reduce; 不管spark底层RDD怎么旋转跳跃成DAG; 不管Flink底层怎么state存储,我们都可以用一句简单的 select * from table 实现我们的基本业务需求。有同学要问了,写sql感觉很不cool,学的知识也少了,但是同学,在面对紧急业务需求时还是要以完成需求为首要目标,工作不是学习,职场不是实验室,降低开发维护成本才是真~ 要什么自行车,能用就行,真想学还是靠自己平时业余时间积累的。
言归正传,下面来几个实际工作中遇到的点(以HiveSQL为例)
1. Null值处理
Null值不管在java和sql中都是个很令人头疼的数据,sql中不能用<> null进行圈选,要用is,或者is not, 同时在count时,null值还会分情况计算
count(*):所有行进行统计,包括NULL行
count(1):所有行进行统计,包括NULL行
count(col):对col中非Null进行统计
count(distinct col): 对col中非Null进行统计
2. 语句执行顺序
(5)SELECT (6)DISTINCT <col>
(1)FROM <table>
(2)WHERE <condition>
(3)GROUP BY <col>
(4)HAVING <condition>
(7)ORDER BY <col>
(8)LIMIT <num>
3. Case when 和 row_number的合用
-- sql1
SELECT *
,CASE WHEN platform='tm' THEN ROW_NUMBER() OVER(
PARTITION BY shop_name
ORDER BY pay_amt)
ELSE NULL END AS tm_order_rank
FROM table
-- where platform='tm'
-- sql2
SELECT *
,CASE WHEN platform='tm' THEN ROW_NUMBER() OVER(
PARTITION BY CASE WHEN platform='tm' THEN shop_name ELSE NULL END
ORDER BY pay_amt)
ELSE NULL END AS tm_order_rank
FROM table
-- where platform='tm'
两端sql都是对tm平台的门店按照金额排序,首先我们需要知道row_number() over()的发生时间,首先使用该函数时,over()里的分组排线执行晚于where,group by,order by,因此当限制where platform条件和case when的一致时结果一样,但是当去掉条件时,结果会不同,sql1的结果不是连续排名,sql2是连续的,原因是什么?问题在于内外层的case when的效果是不同的:
内层的case when进行条件限制分组, 意思是只有满足case when条件的才进行分组, 否则都是null
外层的case when作用是判读结果是否符合,即满足条件的显示排名结果,否则不显示
因此两端sql都只会显示platform=tm的排名数据,而只有内部加了case when的条件排序结果是1,2,3,4,内部没有case when的按照全部shop_name排序,只展示platform=tm的排名
4. 数据倾斜常用处理手段
a. 改参数
b. 大小表关联用mapjoin
c. 少用count distinct
d. 少用动态分区
e. 特殊值单独处理再union all
f. 对主键做md5之后分组处理
5. 有主键的情况下如何找脏数据
SELECT rowkey
FROM TABLE
GROUP BY rowkey
HAVING count(1) > 1;
6. GROUPING SET
表 c1, c2, c3, cnt, 要求对c1, c2, c3分别统计,如何快速编写SQL
select c1
,c2
,c3
,Grouping__ID as group_id
,sum(cnt)
from table
group by c1
,c2
,c3
grouping sets(
(c1)
,(c2)
,(c3)
,(c1,c2)
,(c2,c3)
,(c1,c3)
,(c1,c2,c3)
)