Hive SQL初级练习(30题)

前言

Hive 的重要性不必多说,离线批处理的王者,Hive 用来做数据分析,SQL 基础必须十分牢固。

环境准备

建表语句

这里建4张表,下面的练习题都用这些数据。

-- 创建学生表
create table if not exists student_info(
    stu_id string COMMENT '学生id',
    stu_name string COMMENT '学生姓名',
    birthday string COMMENT '出生日期',
    sex string COMMENT '性别'
)
row format delimited fields terminated by ','
stored as textfile;

-- 创建课程表
create table if not exists course_info(
    course_id string COMMENT '课程id',
    course_name string COMMENT '课程名',
    tea_id string COMMENT '任课老师id'
)
row format delimited fields terminated by ','
stored as textfile;

-- 创建老师表
create table if not exists teacher_info(
    tea_id string COMMENT '老师id',
    tea_name string COMMENT '学生姓名'
)
row format delimited fields terminated by ','
stored as textfile;

-- 创建分数表
create table if not exists score_info(
    stu_id string COMMENT '学生id',
    course_id string COMMENT '课程id',
    score int COMMENT '成绩'
)
row format delimited fields terminated by ','
stored as textfile;

数据

student_info.txt

001,彭于晏,1995-05-16,男
002,胡歌,1994-03-20,男
003,周杰伦,1995-04-30,男
004,刘德华,1998-08-28,男
005,唐国强,1993-09-10,男
006,陈道明,1992-11-12,男
007,陈坤,1999-04-09,男
008,吴京,1994-02-06,男
009,郭德纲,1992-12-05,男
010,于谦,1998-08-23,男
011,潘长江,1995-05-27,男
012,杨紫,1996-12-21,女
013,蒋欣,1997-11-08,女
014,赵丽颖,1990-01-09,女
015,刘亦菲,1993-01-14,女
016,周冬雨,1990-06-18,女
017,范冰冰,1992-07-04,女
018,李冰冰,1993-09-24,女
019,邓紫棋,1994-08-31,女
020,宋丹丹,1991-03-01,女

teacher_info.txt

1001,张高数
1002,李体音
1003,王子文
1004,刘丽英

course_info.txt

01,语文,1003
02,数学,1001
03,英语,1004
04,体育,1002
05,音乐,1002

score_info.txt

001,01,94
002,01,74
004,01,85
005,01,64
006,01,71
007,01,48
008,01,56
009,01,75
010,01,84
011,01,61
012,01,44
013,01,47
014,01,81
015,01,90
016,01,71
017,01,58
018,01,38
019,01,46
020,01,89
001,02,63
002,02,84
004,02,93
005,02,44
006,02,90
007,02,55
008,02,34
009,02,78
010,02,68
011,02,49
012,02,74
013,02,35
014,02,39
015,02,48
016,02,89
017,02,34
018,02,58
019,02,39
020,02,59
001,03,79
002,03,87
004,03,89
005,03,99
006,03,59
007,03,70
008,03,39
009,03,60
010,03,47
011,03,70
012,03,62
013,03,93
014,03,32
015,03,84
016,03,71
017,03,55
018,03,49
019,03,93
020,03,81
001,04,54
002,04,100
004,04,59
005,04,85
007,04,63
009,04,79
010,04,34
013,04,69
014,04,40
016,04,94
017,04,34
020,04,50
005,05,85
007,05,63
009,05,79
015,05,59
018,05,87

加载数据

加载数据到 Hive 的数据源目录

load data local inpath '/opt/module/hive-3.1.2/datas/student_info.txt' into table student_info;
load data local inpath '/opt/module/hive-3.1.2/datas/teacher_info.txt' into table teacher_info;
load data local inpath '/opt/module/hive-3.1.2/datas/course_info.txt' into table course_info;
load data local inpath '/opt/module/hive-3.1.2/datas/score_info.txt' into table score_info;

第一章 简单查询

1.1、查找特定条件

重点就是一个 where ,可能涉及到一点多表联结。

1.1.1 查询姓名中带“冰”的学生名单

简单的可以用 like 配合 % 和 _ ,复杂的可以使用 Hive 扩展的 rlike 配合正则表达式。 

-- 查询姓名中带“冰”的学生名单
select * from student_info where stu_name like '%冰%';

1.1.2 查询姓“王”老师的个数

-- 查询姓“王”老师的个数
select count(*) from teacher_info where tea_name like '王%';
-- 或者
select count(*) from teacher_info where tea_name rlike '^王';

1.1.3 检索课程编号为“04”且分数小于60的学生的课程信息,结果按分数降序排列

通过 course_id 联结两张表,找到不及格的成绩所对应的课程信息。

select c.* from course_info c
join score_info s on c.course_id = s.course_id
where c.course_id = 4 and s.score < 60
order by s.score desc;

1.1.4 查询数学成绩不及格的学生和其对应的成绩,按照学号升序排序

  1. 查询数学课对应的 course_id 
  2. 通过该 course_id 在 score_info 表中查出不及格的成绩的学生信息
  3. 通过学生信息中的 stu_id 字段将 score_info 表和 student_info 表联结起来,输出需要的字段(学生信息,成绩)。 
select stu.*,s.score from student_info stu
join (
    select * from score_info
    where course_id =
          (select course_id from course_info where course_name = '数学')
)s
    on s.stu_id = stu.stu_id
where s.score < 60
order by stu.stu_id;

第二章 汇总分析

2.1 汇总分析

这里需要注意的是,聚合函数必须要和 group by 配合使用!表示分组再做聚合处理。

2.1.1 查询编号为“02”的课程的总成绩

--查询编号为“02”的课程的总成绩
select course_id,sum(score) from score_info where course_id = 02
group by course_id;

2.1.2 查询参加考试的学生个数

select count(distinct stu_id) from score_info;

2.2 分组

重点就是一个 group by。

2.2.1 查询各科成绩最高和最低的分,显示格式:课程号,最高分,最低分

不同的科目对应不同的 course_id ,所以我们用 group by course_id。

-- 同样这里有聚合函数就必须配合 group by 来使用
select course_id,max(score) max,min(score) min from score_info
group by course_id;

2.2.2 查询每门课程有多少学生参加了考试

select course_id, count(stu_id) from score_info
group by course_id;

2.2.3 查询男生、女生人数

-- 查询男生、女生人数
select sex,count(stu_id) from student_info
group by sex;

2.3 分组结果的条件

重点就是 group by 之后的条件判断语句用 having。

2.3.1 查询平均成绩大于60分的学生的学号和平均成绩

这里需要先分组后判断,所以不能用 where,因为 group by 后面的条件语句只能是 having。

-- 这里需要分组后再判断条件
select stu_id,avg(score) avg_score from score_info
group by stu_id
having avg_score>60;

2.3.2 查询至少选修四门课程的学生学号

-- 查询至少选修四门课程的学生学号
select stu_id,count(course_id) cnt from score_info
group by stu_id
having cnt>=4;

2.3.3 查询同姓的学生名单并统计同姓人数大于2的姓

这里用到一个没用过的函数 substr() ,需要记忆一下。

select t1.first_name,count(stu_id) cnt from (
     select *,substr(stu_name,0,1) first_name from student_info
   )t1
group by t1.first_name
having cnt>=2;

2.3.4 查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列

多重排序判断直接逗号隔开即可。

-- 查询每门课程的平均成绩,结果按平均成绩升序排序,平均成绩相同时,按课程号降序排列
select course_id,avg(score) avg_score from score_info
group by course_id
order by avg_score,course_id desc ;

2.3.5 统计参加考试人数大于等于15的学科

-- 统计参加考试人数大于等于15的学科
select course_id,count(*) cnt from score_info
group by course_id
having cnt>=15;

2.4 查询结果排序&分组指定条件

2.4.1 查询学生的总成绩并按照总成绩降序排序

-- 查询学生的总成绩并按照总成绩降序排序
select stu_id,sum(score) sum_score from score_info
group by stu_id
order by sum_score desc;

2.4.2 按照 学生id  语文    数学    英语   有效课程数      平均成绩 的格式输出成绩,没有成绩的记为 0

这里用到了 Hive 中的 if 语句,它的语法是:

IF(condition, true_value, false_value)

其中,condition是要评估的条件,true_value是当条件为真时要返回的值,false_value是当条件为假时要返回的值。

比如;

SELECT name, age, IF(age >= 18, 'Adult', 'Minor') AS age_group  
FROM users;

此外,还可以使用多重 if 嵌套语句:

SELECT name, age,   
  IF(age >= 18 AND gender = 'Male', 'Adult Male',   
     IF(age >= 18 AND gender = 'Female', 'Adult Female',   
        IF(age < 18 AND gender = 'Male', 'Minor Male', 'Minor Female'))) AS age_group  
FROM users;

本题:这里的反引号是引用的作用,这里代表的是 列名。

select s.stu_id,
       sum(if(c.course_name='语文',score,0)) `语文`,
       sum(if(c.course_name='数学',score,0)) `数学`,
       sum(if(c.course_name='英语',score,0)) `英语`,
       count(*) `有效课程数`,
       avg(s.score) `平均成绩`
from score_info s
    join course_info c on s.course_id = c.course_id
group by s.stu_id
order by `平均成绩` desc ;

2.4.3 查询一共参加三门课程且其中一门为语文课程的学生的id和姓名

有点复杂,需要好好理解掌握。

-- 查询一共参加三门课程且其中一门为语文课程的学生的id和姓名
select t2.stu_id,s.stu_name from (
select t1.stu_id from (
    select stu_id,course_id from score_info where stu_id in (
        select stu_id from score_info
        where course_id = '01'
        ) -- 筛选出有语文成绩的学生的id
    ) t1 
        group by t1.stu_id
        having count(t1.course_id)=3
    ) t2
join student_info s on t2.stu_id = s.stu_id;

第三章 复杂查询

3.1 子查询

3.1.1 查询所有课程成绩均小于60分的学生的学号、姓名

我们根据 stu_id 把每个学生的成绩信息聚合在一起。然后巧妙的使用了 if 语句来判断是否有不及格的科目,如果>=60分,结果+1,最后用 sum 函数统计出结果,如果 sum 等于0,则说明全部不及格。

-- 查询所有课程成绩均小于60分的学生的学号、姓名
select t1.stu_id,s.stu_name from(
    select stu_id,sum(if(score>=60,1,0)) flag from score_info
        group by stu_id
        having flag=0
    ) t1
join student_info s on s.stu_id = t1.stu_id;

3.1.2 查询没有学全所有课的学生的学号、姓名

-- 查询没有学全所有课的学生的学号、姓名
select
    s.stu_id,
    s.stu_name
from student_info s
left join score_info sc on s.stu_id = sc.stu_id
group by s.stu_id, s.stu_name
having count(course_id) < (select count(course_id) from course_info)

3.1.3 查询出只选修了三门课程的全部学生的学号和姓名

select
    s.stu_id,
    s.stu_name
from student_info s
join (
    select
        stu_id,
        count(course_id) course_count
    from score_info
    group by stu_id
    having course_count =3
    ) t1
on s.stu_id = t1.stu_id;

第四章 多表查询

4.1 表联结

4.2 多表连接

你可能感兴趣的:(Hive,SQL,hive,sql,hadoop)