数据表和需求

表名:student, 结构和具体内容如下:
name course score
zs  Math    100
zs  Engl    80
ls  Math    90
ls  Engl    70需求如下:
1、获取每个学生最高分对应的学科和分数
(方式一:使用row_number()开窗函数;方式二:不用开窗函数,使用join方式)
扩展:返回每一门课程和对应的最高分的学生姓名(思路:将分组的学生替换为学科即可,此处不再赘述)
2、获取每门课程都高于平均分的人、课程和分数

数据准备

set hive.exec.mode.local.auto=true;
set hive.cli.print.header=true;create table student stored as orc as
select 'zs' as name, 'Math' as course, 100 as score union all
select 'zs' as name, 'Engl' as course, 80  as score union all
select 'ls' as name, 'Math' as course, 90  as score union all
select 'ls' as name, 'Engl' as course, 70  as score;

需求1:获取每个人最高分对应的学科和分数
第一步:使用开窗函数,用row_number(), 按name分组,每个人的分数排序,
第二步:排好序后,取出每个人的最高分即可

----------------- 方式一 使用row_number() ---------------
select name,course,score
from(select name,course,score,row_number() over(partition by name order by score desc) row_numfrom student
)t
where row_num = 1;
----------------- 查询结果 ---------------
name    course  score
ls  Math    90
zs  Math    100

扩展:返回每一门课程和对应的最高分的学生姓名(思路:用学科分组替换学生分组,不再赘述)

----------------- 方式二 使用join ---------------
--思路:先获取每个学生的最高分,去join原表即可拿到
selects.name,s.course,s.score
from student s
join(select name,max(score) as max_scorefrom studentgroup by name
)t
on s.name = t.name and s.score = t.max_score;
----------------- 查询结果 ---------------
s.name  s.course    s.score
ls  Math    90
zs  Math    100

需求2:获取每门课程都高于平均分的人、课程和分数
减法实现:所有课程高于平均分的人 = 所有人 - 至少一门低于平均分的人

第一步:先求每门课程的平均分,得到临时表 t1
第二步:找出有某门课程小于平均分的人,得到临时表 t2
第三步:原表left join t2,让 t2 中 name 为空,则反向获取到每门课程均高于平均分的人
注意点:有一个思维转换:不容易直接找出同时多门课程都高于平均分的人,
可以反向找出只要有一门课程小于平均分,那这个人一定不是所有课程都高于平均分的人

-------- 测试查询 满足条件的人和课程;但是多行,最终每个人需转为一行数据,见下一条sql  -----
select name,course,score
from abc
left join(selectif(abc.score < t1.avg_score, abc.name, null) as name,from abcjoin (selectcourcesum(score)  / count(*) as avg_scorefrom abcgroup by course)t1on abc.course = t1.course
)t2
on abc.name = t2.name
where t2.name is null;
----------------- 查询结果 ---------------
s.name  s.course    s.score
zs  Math    100
zs  Engl    80

另外注意点: if(s.score < t1.avg_score, s.name, rand()) as name
判断分数低于平均分时,如果非,则用rand()代替,这样避免后面join时出现,倾斜key

-------- 最终sql查询 满足条件的人和课程;但是多行,最终每个人转一行数据  -----create table tmp stored as orc as
select s.name,collect_list(concat_ws(':', array(s.course, s.score))) as detail_array,concat_ws(',',collect_list( concat_ws(':', array(s.course, s.score) ) )) as detail_string
from student s
left join(selectif(s.score < t1.avg_score, s.name, rand()) as namefrom student sjoin (selectcourse,sum(score) / count(*) as avg_scorefrom studentgroup by course)t1on s.course = t1.course
)t2
on s.name = t2.name
where t2.name is null
group by s.name;
----------------- 查询结果 ---------------
s.name  detail_array    detail_string
zs  ["Math:100","Engl:80"]  Math:100,Engl:80

注意:字段类型根据最终需求看是否转 string,还是array
(1) string更容易和其他数据库间导入导出,如mysql没有array类型,可能会有一点麻烦
(2) array容易获取对应位置的数据

hive> desc tmp;
OK
col_name    data_type   comment
name                    string
detail_array            array<string>
detail_string           string----------获取某一个位置的值
hive> select detail_array[1] as course_score from tmp;
course_score
Engl:80hive> select detail_array[0] as course_score from tmp;
course_score
Math:100

3、获取每个学科都及格(>=60分)的学生

--方式一: 使用having方式,仅一个job(比较好方式) ----------
select
name
from student_copy
group by name
having min(score)> 60;
--结果如下: ------------
ls
zs
Time taken: 1.305 seconds, Fetched: 2 row(s)-- 比较笨重的方式:会有4个job(不建议,只是对比两个) -------
selectdistinct s.name
from student_copy s
left join (selectnamefrom student_copywhere score < 60group by name
)t1
on s.name=t1.name
where t1.name is null;
--结果如下
ls
zs
Time taken: 12.298 seconds, Fetched: 4 row(s)

Hive实现:1、获取每个人最高分对应的学科和分数(学生最高分);2、获取每门课程都高于平均分的人、课程和分数(三好学生:每科高于平均分);3、获取每个学科都及格(即不低于60分)的学生相关推荐

  1. 数据库练习题(大于或等于80表示优秀,大于或等于60表示及格,小于60分表示不及格)

    数据库创建字段 2.填写SQL语句 SQL语句 select (case when 语文>=80 then '优秀' when 语文>=60 then '及格' else '不及格' en ...

  2. sql统计各科成绩大于平均分的人_数据分析师SQL面试必备50题

    以下是SQL面试必备的经典的50道题目,每道题都有博主本人的解题思路和对应的SQL语句. 每道题的思路与答案均为博主本人主观理解,仅供参考. 环境:MySQL8.0 可视化工具:Navicat 1.查 ...

  3. 浙大版《C语言程序设计(第3版)》题目集 练习3-3 统计学生平均成绩与及格人数 (15 分)...

    练习3-3 统计学生平均成绩与及格人数 (15 分) 本题要求编写程序,计算学生们的平均成绩,并统计及格(成绩不低于60分)的人数.题目保证输入与输出均在整型范围内. 输入格式: 输入在第一行中给出非 ...

  4. 查询各科成绩都大于80分的学生成绩

    成绩表 score stuname   subjectname   score A         语文                 70 A         数学                 ...

  5. 高考 | 满分作文:《我们都是读“书”人》

    我们都是读"书"人 浙江考生 阿根廷作家博尔赫斯曾言:"如果有天堂,应该是图书馆的样子."人立于世,世界就是一本大书.诚如材料中作家所言,人生三本大书是为&qu ...

  6. 都说“先卖人,后卖货”,或者说要想卖货,先卖人

    都说"先卖人,后卖货",或者说要想卖货,先卖人.其实,"卖人"和"卖货"很多时候是两套逻辑. 卖人很大程度上是卖服务,卖虚拟产品,比如卖&q ...

  7. 题9.5:有10个学生,每个学生的数据包括学号、姓名、3门课程的成绩,从键盘输人10个 学生数据,要求输出3门课程总平均成绩,以及最高分的学生的数据(包括学号、姓 名、3门课程成绩、平均分数)。

    题目 本题是谭浩强<C程序设计课后习题>题9.5. 题目: 有10个学生,每个学生的数据包括学号.姓名.3门课程的成绩,从键盘输人10个 学生数据,要求输出3门课程总平均成绩,以及最高分的 ...

  8. vivo壁纸Android版,安卓福利:来自VIVO X20全面屏原生壁纸 每一张都美的让人窒息!...

    原标题:安卓福利:来自VIVO X20全面屏原生壁纸 每一张都美的让人窒息! 好看的皮囊千篇一律,有趣的灵魂万里挑一,有时候想要找一张称心如意的壁纸可不是一件容易的事情,为此,各大厂商也是殚精竭虑,想 ...

  9. 软考科目包含哪些?每个科目都适合什么样的人考?

    软考包含多个科目,考试难度因科目而异.想要选择适合自己的软考科目,需要了解每个科目的考试内容.难度,以及自己的职业发展规划和个人能力水平. 一.软考科目包含哪些? 软考一共有27个科目,分为初级.中级 ...

最新文章

  1. Visual Box 比Visual Pc 好用
  2. java bitmap获取图片大小_android 通过uri获取bitmap图片并压缩
  3. 突发热点事件下微博高可用注册中心vintage的设计\u0026实践
  4. curl和wget的区别和使用
  5. windows Navicat Premium连接oracle
  6. Android 中文API (46) —— SimpleAdapter
  7. android 视频美颜,Android短视频中如何实现720P磨皮美颜录制?
  8. 从39个kaggle竞赛中总结出来的图像分割的Tips和Tricks
  9. ResultSet的getDate()、getTime()和getTimestamp()比较
  10. vscode 支持ansi_vscode terminal美化
  11. MongoDB - 使用Python操作MongoDB
  12. Merge the incoming changes into the current branch
  13. php动态web开发技术,PHP动态Web开发技术
  14. IC卡读写器VB.NET源代码
  15. Matlab制作高分辨率点线图
  16. 子网掩码最简单通俗的解释
  17. 浅谈程序脱壳后的优化
  18. Java、JSP公文流转系统分析与实现
  19. ubuntu虚拟机ping通内网
  20. Linux替换压缩包下的文件,Linux下rar及zip压缩包中批量替换某文件脚本

热门文章

  1. 金山云VR+8K超高清直播全链路解决方案
  2. python人物抠图算法_Python实现AI自动抠图实例解析
  3. html中frame背景颜色,如何修改frame窗口的背景颜色?
  4. 一位开发大神的“告别信”!
  5. 面试官问你为什么选择做客服_在线客户服务-您的选择
  6. 苹果电脑ntfs如何打开硬盘?mac能读取的硬盘格式
  7. python 网页自动化实现
  8. 简述python在量化金融中应用_Python金融量化
  9. linux编写多时区时间显示程序,Linux系统时区时间修改
  10. 【5G】5G通信网络中资源分配和负载均衡算法的matlab仿真