(图片付费下载自视觉中国)
作者 | 石晓文
来源|小小挖掘机(ID:wAlsjwj)
近期在不同群里有小伙伴们提出了一些在面试和笔试中遇到的Hive SQL问题,Hive作为算法工程师的一项必备技能,在面试中也是极有可能被问到的,所以有备无患,本文将对这四道题进行详细的解析,还是有一定难度的,希望你看完本文能够有所收获。

1、多列转多行

第一道题目是这样的:
假设现有一张Hive表,
元数据格式为:字段:
id    stirng
tim    string数据格式如下:
a,b,c,d 2:00,3:00,4:00,5:00
f,b,c,d    1:10,2:20,3:30,4:40需要变成:
a     2:00
b     3:00
c     4:00
d     5:00
这道题目是需要把多行转换成多行,有点类似python里面的zip操作。大伙应该都知道hive里有一个常用的一行转多行的函数叫explode,假设有如下的数据:
a,b,c,d 2:00,3:00,4:00,5:00
f,b,c,d    1:10,2:20,3:30,4:40
按照第二列explode的话,使用下面的SQL:
selectid,tim,single_tim
fromdefault.a1lateral view explode(split(tim,',')) t as single_tim
效果如下:

但这道题目里,需要对两列同时进行explode,如果只进行简单的explode,效果如下:

这样一行变成了16行,而我们仅仅需要的是其中能够对齐下标的四行。所以在进行explode的时候,我们期望不仅仅能够能够获得数组里的每个值,还希望能够得到其对应的下标,这样在对两列同时进行explode的时候,保留数组下标相同的四行就可以了。这里我们会用到posexplode函数。
posexplode函数跟explode函数的使用方法类似,看下面的例子:
selectid,tim,single_id_index,single_id
fromdefault.a1lateral view posexplode(split(id,',')) t as single_id_index,single_id
返回的结果为:

应用到本题,只需要应用两次posexplode函数,再通过where留下两个index相等的行就可以了,按照这个思路,sql如下:
selectid,tim,single_id,single_tim
fromdefault.a1lateral view posexplode(split(id,',')) t as single_id_index,single_idlateral view posexplode(split(tim,',')) t as single_tim_index,single_tim
wheresingle_id_index = single_tim_index
结果正是我们想要的:

2、排序后相邻两行均值

第二题的原始数据如下:

要求如下:

分组排序想必大家都知道使用row_number()函数,但要找到同组前一行的值,可能有许多同学不太了解,这里是用的是lead/lag函数,两个函数用法如下:
lag(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)lead(字段名,N) over(partition by 分组字段 order by 排序字段 排序方式)
lag括号里理由两个参数,第一个是字段名,第二个是数量N,这里的意思是,取分组排序之后比该条记录序号小N的对应记录的指定字段的值,如果字段名为ts,N为1,就是取分组排序之后上一条记录的ts值。
lead括号里理由两个参数,第一个是字段名,第二个是数量N,这里的意思是,取分组排序之后比该条记录序号大N的对应记录的对应字段的值,如果字段名为ts,N为1,就是取分组排序之后下一条记录的ts值。
如果没有前一行或者后一行,对应的字段值为null。
所以,这里我们应该使用的是lag函数,来获取同组排序后前一行数据对应字段的值,SQL如下:
selectyear,chr,if(pre_val is null,val,(val + pre_val) / 2.0) as avg_val
from
(
selectyear,chr,val,lag(val,1) over(partition by year order by chr asc) as pre_val
fromdefault.a2
) a
注意这里的一个小细节,如果分组后数据排在第一位,它是没有前一个数的,此时数仍保持原样,所以这里加了一个if判断,结果符合预期:

3、获取字符串索引列表

第三题的题目要求如下:
1011
0101
=> 取到每一行中1所对应的索引列表,索引从1开始
0101    2,4
1011    1,3,4
这一行其实也是对posexplode方法的应用,直接上代码:
selectid,stri,concat_ws(',',collect_list(index)) as indices
from
(selectid,stri,chr,cast(index + 1 as string) as indexfromdefault.abcglateral view posexplode(split(stri,'')) ids as index,chrwherechr = '1'
) a
group byid,stri

4、分块排序

最后一题感觉是比较有难度的一道题目:
2014,1
2015,1
2017,0
2018,0
2019,1
2020,1
2021,1
2022,0
2023,0
=>
2014,1,1
2015,1,2
2017,0,1
2018,0,2
2019,1,1
2020,1,2
2021,1,3
2022,0,1
2023,0,2
简单描述下题目,col1是有序的,然后按照col2分块计数,每当col2发生变化,就重新开始计数,计数的结果当作col3返回。
这道题我想到的方法可能比较笨,先上代码,然后咱们一步步解析:
select year,num,row_number() over(partition by min_year order by year asc) as new_rankfrom(select year,base.num as num,min_year,row_number() over(partition by base.year order by min_year desc) as rankfrom (select *from default.a3) baseinner join (select min_year,num,pre_numfrom (select year as min_year,num,lag(num,1) over(order by year) as pre_numfrom default.a3) awhere num!=pre_numor pre_num is null) min_yearon base.num = min_year.numwhere base.year >= min_year.min_year) ccwhere rank = 1order by year
输出结果符合预期:

接下来,一步步解析下上面的过程:
1)使用lag函数,得到其前面一个数:
select year as min_year,num,lag(num,1) over(order by year) as pre_numfrom default.a3
2)判断当前数和前面一个数的关系,得到分块最小值。
如果两个数不相等,说明在此处数发生了变化,是一个新的分块的开始,除此之外,如果没有前一个数,说明当前行是第一行,同样作为一个分块的开始。这样,我们可以得到每个分块的开始:
select min_year,num,pre_num
from (select year as min_year,num,lag(num,1) over(order by year) as pre_numfrom default.a3) a
where num!=pre_numor pre_num is null
这里的结果如下:

四个分块的开始分别是2014、2017、2019、2022。
3)判断每一行属于哪个分块
我们需要拿第二步得到的结果与原结果使用第二列进行join,然后判断每一行属于哪个分块。决定每一行的所属分块有两个条件,首先该行第一列的值要大于或等于分块的最小值;其次,在所有满足条件的分块最小值中,选择最大的一个,便是该行所在分块的最小值。
所以这里我们首先进行join操作,然后使用row_number()得到了每一行所在的分块:
select year,num,min_yearfrom(select year,base.num as num,min_year,row_number() over(partition by base.year order by min_year desc) as rankfrom (select *from default.a3) baseinner join (select min_year,num,pre_numfrom (select year as min_year,num,lag(num,1) over(order by year) as pre_numfrom default.a3) awhere num!=pre_numor pre_num is null) min_yearon base.num = min_year.numwhere base.year >= min_year.min_year) ccwhere rank = 1order by year
结果如下:

4)把分块最小值作为分组键,进行分组排序
好了,这四道题就解析完毕了,抓紧时间去练习一下吧~~
(*本文为 AI大本营转载文章,转载请联系原作者。)

精彩推荐

推荐阅读

  • 鸿蒙 OS 的到来,能为我们改变什么?

  • 干货 | OpenCV看这篇就够了,9段代码详解图像变换基本操作

  • 周杰伦的《说好不哭》,20万点评Python来分析

  • 算法人必懂的进阶SQL知识,4道面试常考题

  • 6张拓扑图揭秘中心化交易所的5种行为, 原来中心化比你想象的重要

  • 分布式存储春天已来Storj首登top10; Cardano排名上升; 以太坊比特币活跃地址双下降 | 数据周榜

  • 华为愿出售5G技术渴望对手;苹果将向印度投资10亿美元;华为全联接大会首发计算战略;腾讯自研轻量级物联网操作系统正式开源……

  • TDD 就是个坑

  • 厉害!接班马云的为何是张勇?

你点的每个“在看”,我都认真当成了喜欢

算法人必懂的进阶SQL知识,4道面试常考题相关推荐

  1. gc日志一般关注什么_Java架构师必懂的GC日志知识

    在Java,Android,C#等中,GC是自动的,而在几种前代编程语言(C,C ++)中,程序员必须明确编写代码才能释放对象. 所以,这对于Java,Android和C#应用程序开发人员来说是一个很 ...

  2. 光E电4个必懂的理财基础知识

    现在越来越多的人意识到理财的重要性.理财不只要有正确的出资,也要有专业的理财办法.做好出资理财的关键所在掌握必要的出资理财根底知识,才华助理财一臂之力. 1.不明白的东西不要碰 这是最重要的一个概念. ...

  3. 非期望产出的sbm模型_KANO模型:产品人必懂的需求分析法

    需求会因人而异,会因文化差异而不同:也会随着时间变化.作为产品设计者,我们应该持续调研需求,对产品进行迭代优化. 在做项目做产品的过程中,作为互联网产品设计师的我们,经常会接到来自PM/领导/业务方等 ...

  4. KANO模型(卡诺模型):产品人必懂的需求分析法

    在做项目做产品的过程中,作为互联网产品设计师的我们,经常会接到来自PM/领导/业务方等等的各种需求. 有的时候,哪怕一个小功能.次次次级页面都会争得不可开交.这个时候怎么办呢?到底应该听谁的呢?哪个需 ...

  5. 会计人必知的实务基础知识

    在实务工作中可能每个财务人员只负责某一个会计工作环节,尽管如此,每个财务人员还是非常有必要对财务工作的大致环节了如指掌. 一.财务工作的大致环节如下: 1.根据原始凭证或原始凭证汇总表填制记账凭证. ...

  6. 运营人必懂 | TikTok运营指南

    "TikTok之前确实很火,现在呢?" 最新数据告诉你: Sensor Tower商店情报数据显示,2022年9月抖音及海外版TikTok在全球App Store和Google P ...

  7. 心理学:情商高的人必懂的三大沟通技巧

    情商高的人意味着会说话,他所说的话让人不由自主的接受,其实情商高的人擅长沟通, 在心理学上来说,也是有套路的: 情商高手交流 1.让人印象深刻,尝试用"补偿称赞技巧" 如果我们想要 ...

  8. 网络工程师必懂的网络基础知识

    ✈前些天发现了一个巨牛的人工智能学习网站,通俗易懂,风趣幽默,忍不住分享一下给大家:床长人工智能教程 文章目录 1 ip地址 1.1 ip 地址的作用?ip 地址分类? 1.2. 子网掩码的作用?默认 ...

  9. 〖编程初学者的自我修养 - 职业规划篇④〗- 优秀职人必懂、必会的职业规划

    历时18个月,采访 850+ 得到的需求. 不管你是在校大学生.研究生.还是在职的小伙伴,该专栏有你想要的职业规划.简历.面试的答案. 说明:该文属于 编程初学者的自我修养 专栏,购买任意白宝书体系化 ...

最新文章

  1. skiplist跳表的 实现
  2. 洛谷P3572 [POI2014]PTA-Little Bird
  3. Github标星3K+,超轻量级中文OCR,支持竖排文字识别、ncnn推理,总模型仅17M
  4. 如何建立一个数据分析团队?
  5. RuntimeError: Bool type is not supported by dlpack
  6. JQuery 动画卷页 -- 返回顶部 动画特效(兼容Chrome)
  7. Java中try必须要结合catch吗_如何优雅的实现 try/catch 异常块?
  8. ASP.NET使用ConfigurationSection在Web.Config创建自定义配置节
  9. 将android界面背景设置为黑色
  10. 10个最佳的网站和App开发工具
  11. linux系统取代windows,Linux替代Windows系统软件大比拼
  12. 板级电源究竟该怎么选型芯片?(实战篇)
  13. VS Code:推荐插件 - HTML格式化(包括JS、CSS)
  14. kafka auto.offset.reset参数解析
  15. 大数(10^9)求欧拉数
  16. u盘插电脑上不显示怎么办?数据恢复还有希望吗
  17. 三方协议中的服务器,手把手教你三方协议怎么填
  18. 正则表达式:必须包含数字,小写,大写,符号
  19. 赢在测试2:中国软件测试专家访谈录
  20. Inno Setup软件 打包多个安装包程序

热门文章

  1. LVM 类型的 Storage Pool - 每天5分钟玩转 OpenStack(8)
  2. python 利用模板文件生成配置文件
  3. SqlParameter的用法
  4. Oracle:彻底结束会话 ,彻底解锁
  5. Qt嵌入外部EXE程序,并显示在主界面中!
  6. buffers与cached的区别
  7. mail 发送email
  8. BGA封装芯片手工焊接攻略
  9. 精通JavaScript--07设计模式:行为型
  10. jQuery的文档操作方法