第12周 hive sql综合训练(二)

第12周 · hive sql综合训练(二)

综合查询训练二:复杂查询与多表查询

项目9阶段06单元5 Hive数据查询单元7 Hive性能优化

本实训对应的知识点

实训内容与步骤 依据原始实训文档整理,命令与配置均来自文档原文

1.1多表查询

1.1.1表联结

(1)如图1-1所示,查询有两门以上的课程不及格的同学的学号及其平均成绩

① 先找出有两门以上不及格的学生名单,按照学生分组,过滤组内成绩低于60的并进行count,count>=2。

② 接着做出一张表查询学生的平均成绩并和上一个子查询中的学生学号进行连接

SHELL
hive>

select

t1.stu_id,

t1.avg_score

SQL
from (

select

stu_id,

SQL
sum(if(score < 60,1,0)) flage
from score_info
group by stu_id
having flage >= 2
) t1

join (

select

stu_id,

SQL
avg(score) avg_score
from score_info
group by stu_id
) t2 on t1.stu_id = t1.stu_id;

结果

📷 图1-1 查询有两门以上的课程不及格的同学的学号及其平均成绩

(2) 如图1-2所示,查询所有学生的学号、姓名、选课数、总成绩

select

s.stu_id,

s.stu_name,

SQL
count(sc.course_id) count_course,
sum(sc.score) sum_score
from student_info s
left join score_info sc on s.stu_id = sc.stu_id
group by s.stu_id,s.stu_name;

结果

📷 图1-2 查询所有学生的学号、姓名、选课数、总成绩

(3)如图1-3所示,查询平均成绩大于85的所有学生的学号、姓名和平均成绩

SQL
select s.stu_id,

s.stu_name,

SQL
avg(sc.score) avg_score
from score_info sc
left join student_info s on s.stu_id = sc.stu_id
group by s.stu_id, s.stu_name
having avg_score > 85

结果

📷 图1-3查询平均成绩大于85的所有学生的学号、姓名和平均成绩

(4) 如图1-4所示,查询学生的选课情况:学号,姓名,课程号,课程名称

select

s.stu_id,

s.stu_name,

c.course_id,

c.course_name

TEXT
from score_info sc
join course_info c on sc.course_id = c.course_id
join student_info s on sc.stu_id = s.stu_id;

结果

📷 图1-4查询学生的选课情况:学号,姓名,课程号,课程名称

(5)如图9-5所示,查询出每门课程的及格人数和不及格人数

select

c.course_id,

c.course_name,

t1.`及格人数`,

t1.`不及格人数`

TEXT
from course_info c

join (

select

course_id,

SQL
sum(if(score >= 60,1,0)) as `及格人数`,
sum(if(score < 60,1,0)) as `不及格人数`
from score_info
group by course_id
) t1 on c.course_id = t1.course_id;

结果

📷 图1-5 查询出每门课程的及格人数和不及格人数

(6)如图1-6所示,查询课程编号为03且课程成绩在80分以上的学生的学号和姓名及课程信息

select

s.stu_id,

s.stu_name,

t1.score,

t1.course_id,

c.course_name

TEXT
from student_info s

join (

select

stu_id,

score,

course_id

TEXT
from score_info
where score > 80 and course_id = '03'
) t1
on s.stu_id = t1.stu_id
join course_info c on c.course_id = t1.course_id;

结果

📷 图1-6 查询课程编号为03且课程成绩在80分以上的学生的学号和姓名及课程信息

1.1.2多表连接

(1)如图1-7,课程编号为"01"且课程分数小于60,按分数降序排列的学生信息

select

s.stu_id,

s.stu_name,

s.birthday,

s.sex,

t1.score

TEXT
from student_info s

join (

select

stu_id,

course_id,

score

📷 图1-7课程编号为"01"且课程分数小于60,按分数降序排列的学生信息
TEXT
from score_info
where score < 60 and course_id = '01'
) t1
on s.stu_id=t1.stu_id
order by t1.score desc;

(2)如图1-8所示,查询所有课程成绩在70分以上的学生的姓名、课程名称和分数,按分数升序排列

select

s.stu_id,

s.stu_name,

c.course_name,

s1.score

TEXT
from student_info s

join (

select

stu_id,

SQL
sum(if(score >= 70,0,1)) flage
from score_info
group by stu_id
having flage =0
) t1
on s.stu_id = t1.stu_id
left join score_info s2 on s.stu_id = s1.stu_id
left join course_info c on s1.course_id = c.course_id;

结果如图1-8所示:

📷 图1-8 查询所有课程成绩在70分以上的学生的姓名、课程名称和分数,按分数升序排列

(3)如图1-9所示,查询该学生不同课程的成绩相同的学生编号、课程编号、学生成绩

select

sc1.stu_id,

sc1.course_id,

sc1.score

📷 图1-9查询该学生不同课程的成绩相同的学生编号、课程编号、学生成绩
TEXT
from score_info sc1
join score_info sc2 on sc1.stu_id = sc1.stu_id
and sc1.course_id <> sc1.course_id
and sc1.score = sc1.score;

(4)如图1-10所示, 查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号

知识点:多表连接 + 条件

select

s1.stu_id

from

(

select

sc1.stu_id,

sc1.course_id,

sc1.score

TEXT
from score_info sc1
where sc1.course_id ='01'
) s1

join

(

select

sc1.stu_id,

sc1.course_id,

score

📷 图1-10查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号
TEXT
from score_info sc2
where sc1.course_id ="02"
) s2
on s1.stu_id=s1.stu_id
where s1.score > s1.score;

(5)如图1-11查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名

select

t1.stu_id as `学号`,

s.stu_name as `姓名`

from

TEXT
( select

stu_id

TEXT
from score_info sc1
where sc1.course_id='01'
and stu_id in (

select

stu_id

TEXT
from score_info sc2
where sc1.course_id='02'
) )t1
join student_info s
on t1.stu_id = s.stu_id;

结果如图1-11所示:

📷 图1-11 查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名

(6)如图1-12所示,查询学过“李体音”老师所教的所有课的同学的学号、姓名

select

t1.stu_id,

si.stu_name

from

TEXT
( select

stu_id

TEXT
from score_info si
where course_id in

(

select

course_id

TEXT
from course_info c
join teacher_info t
on c.tea_id = t.tea_id

where tea_name='李体音' --李体音教的所有课程

)

TEXT
group by stu_id

having count(*)=2 --学习所有课程的学生

📷 图1-12 查询学过“李体音”老师所教的所有课的同学的学号、姓名
TEXT
)t1
left join student_info si
on t1.stu_id=si.stu_id;

(7)如图1-13所示,查询学过“李体音”老师所讲授的任意一门课程的学生的学号、姓名

select

t1.stu_id,

si.stu_name

from

TEXT
( select

stu_id

TEXT
from score_info si
where course_id in
( select

course_id

TEXT
from course_info c
join teacher_info t
on c.tea_id = t.tea_id

where tea_name='李体音'

)

TEXT
group by stu_id
)t1
left join student_info si
on t1.stu_id=si.stu_id;

结果

📷 图1-13 查询学过“李体音”老师所讲授的任意一门课程的学生的学号、姓名

(8)如图1-14所示,查询至少有一门课与学号为“001”的学生所学课程相同的学生的学号和姓名

select

si.stu_id,

si.stu_name

TEXT
from score_info sc
join student_info si
on sc.stu_id = si.stu_id
where sc.course_id in

(

select

course_id

TEXT
from score_info

where stu_id='001' --001的课程

) and sc.stu_id <> '001' --排除001学生

TEXT
group by si.stu_id,si.stu_name;

结果如图1-14所示:

📷 图1-14查询至少有一门课与学号为“001”的学生所学课程相同的学生的学号和姓名

(9)如图1-15所示, 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

select

si.stu_name,

ci.course_name,

sc.score,

t1.avg_score

TEXT
from score_info sc
join student_info si
on sc.stu_id=si.stu_id
join course_info ci
on sc.course_id=ci.course_id

join

(

select

stu_id,

SQL
avg(score) avg_score
from score_info
group by stu_id
) t1
on sc.stu_id=t1.stu_id
order by t1.avg_score desc;

结果

📷 图1-15 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

II

📄 展开原始文档全文(276 段)

hive sql综合训练(二)

1.1 多表查询

1.1.1 表联结

(1)如图1-1所示,查询有两门以上的课程不及格的同学的学号及其平均成绩

① 先找出有两门以上不及格的学生名单,按照学生分组,过滤组内成绩低于60的并进行count,count>=2。

② 接着做出一张表查询学生的平均成绩并和上一个子查询中的学生学号进行连接

hive>

select

t1.stu_id,

t1.avg_score

from (

select

stu_id,

sum(if(score < 60,1,0)) flage

from score_info

group by stu_id

having flage >= 2

) t1

join (

select

stu_id,

avg(score) avg_score

from score_info

group by stu_id

) t2 on t1.stu_id = t1.stu_id;

结果

📷 图1-1 查询有两门以上的课程不及格的同学的学号及其平均成绩

(2) 如图1-2所示,查询所有学生的学号、姓名、选课数、总成绩

select

s.stu_id,

s.stu_name,

count(sc.course_id) count_course,

sum(sc.score) sum_score

from student_info s

left join score_info sc on s.stu_id = sc.stu_id

group by s.stu_id,s.stu_name;

结果

📷 图1-2 查询所有学生的学号、姓名、选课数、总成绩

(3)如图1-3所示,查询平均成绩大于85的所有学生的学号、姓名和平均成绩

select s.stu_id,

s.stu_name,

avg(sc.score) avg_score

from score_info sc

left join student_info s on s.stu_id = sc.stu_id

group by s.stu_id, s.stu_name

having avg_score > 85

结果

📷 图1-3查询平均成绩大于85的所有学生的学号、姓名和平均成绩

(4) 如图1-4所示,查询学生的选课情况:学号,姓名,课程号,课程名称

select

s.stu_id,

s.stu_name,

c.course_id,

c.course_name

from score_info sc

join course_info c on sc.course_id = c.course_id

join student_info s on sc.stu_id = s.stu_id;

结果

📷 图1-4查询学生的选课情况:学号,姓名,课程号,课程名称

(5)如图9-5所示,查询出每门课程的及格人数和不及格人数

select

c.course_id,

c.course_name,

t1.`及格人数`,

t1.`不及格人数`

from course_info c

join (

select

course_id,

sum(if(score >= 60,1,0)) as `及格人数`,

sum(if(score < 60,1,0)) as `不及格人数`

from score_info

group by course_id

) t1 on c.course_id = t1.course_id;

结果

📷 图1-5 查询出每门课程的及格人数和不及格人数

(6)如图1-6所示,查询课程编号为03且课程成绩在80分以上的学生的学号和姓名及课程信息

select

s.stu_id,

s.stu_name,

t1.score,

t1.course_id,

c.course_name

from student_info s

join (

select

stu_id,

score,

course_id

from score_info

where score > 80 and course_id = '03'

) t1

on s.stu_id = t1.stu_id

join course_info c on c.course_id = t1.course_id;

结果

📷 图1-6 查询课程编号为03且课程成绩在80分以上的学生的学号和姓名及课程信息

1.1.2 多表连接

(1)如图1-7,课程编号为"01"且课程分数小于60,按分数降序排列的学生信息

select

s.stu_id,

s.stu_name,

s.birthday,

s.sex,

t1.score

from student_info s

join (

select

stu_id,

course_id,

score

from score_info

where score < 60 and course_id = '01'

) t1

on s.stu_id=t1.stu_id

order by t1.score desc;

📷 图1-7课程编号为"01"且课程分数小于60,按分数降序排列的学生信息

(2)如图1-8所示,查询所有课程成绩在70分以上的学生的姓名、课程名称和分数,按分数升序排列

select

s.stu_id,

s.stu_name,

c.course_name,

s1.score

from student_info s

join (

select

stu_id,

sum(if(score >= 70,0,1)) flage

from score_info

group by stu_id

having flage =0

) t1

on s.stu_id = t1.stu_id

left join score_info s2 on s.stu_id = s1.stu_id

left join course_info c on s1.course_id = c.course_id;

结果如图1-8所示:

📷 图1-8 查询所有课程成绩在70分以上的学生的姓名、课程名称和分数,按分数升序排列

(3)如图1-9所示,查询该学生不同课程的成绩相同的学生编号、课程编号、学生成绩

select

sc1.stu_id,

sc1.course_id,

sc1.score

from score_info sc1

join score_info sc2 on sc1.stu_id = sc1.stu_id

and sc1.course_id <> sc1.course_id

and sc1.score = sc1.score;

📷 图1-9查询该学生不同课程的成绩相同的学生编号、课程编号、学生成绩

(4)如图1-10所示, 查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号

知识点:多表连接 + 条件

select

s1.stu_id

from

(

select

sc1.stu_id,

sc1.course_id,

sc1.score

from score_info sc1

where sc1.course_id ='01'

) s1

join

(

select

sc1.stu_id,

sc1.course_id,

score

from score_info sc2

where sc1.course_id ="02"

) s2

on s1.stu_id=s1.stu_id

where s1.score > s1.score;

📷 图1-10查询课程编号为“01”的课程比“02”的课程成绩高的所有学生的学号

(5)如图1-11查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名

select

t1.stu_id as `学号`,

s.stu_name as `姓名`

from

( select

stu_id

from score_info sc1

where sc1.course_id='01'

and stu_id in (

select

stu_id

from score_info sc2

where sc1.course_id='02'

) )t1

join student_info s

on t1.stu_id = s.stu_id;

结果如图1-11所示:

📷 图1-11 查询学过编号为“01”的课程并且也学过编号为“02”的课程的学生的学号、姓名

(6)如图1-12所示,查询学过“李体音”老师所教的所有课的同学的学号、姓名

select

t1.stu_id,

si.stu_name

from

( select

stu_id

from score_info si

where course_id in

(

select

course_id

from course_info c

join teacher_info t

on c.tea_id = t.tea_id

where tea_name='李体音' --李体音教的所有课程

)

group by stu_id

having count(*)=2 --学习所有课程的学生

)t1

left join student_info si

on t1.stu_id=si.stu_id;

📷 图1-12 查询学过“李体音”老师所教的所有课的同学的学号、姓名

(7)如图1-13所示,查询学过“李体音”老师所讲授的任意一门课程的学生的学号、姓名

select

t1.stu_id,

si.stu_name

from

( select

stu_id

from score_info si

where course_id in

( select

course_id

from course_info c

join teacher_info t

on c.tea_id = t.tea_id

where tea_name='李体音'

)

group by stu_id

)t1

left join student_info si

on t1.stu_id=si.stu_id;

结果

📷 图1-13 查询学过“李体音”老师所讲授的任意一门课程的学生的学号、姓名

(8)如图1-14所示,查询至少有一门课与学号为“001”的学生所学课程相同的学生的学号和姓名

select

si.stu_id,

si.stu_name

from score_info sc

join student_info si

on sc.stu_id = si.stu_id

where sc.course_id in

(

select

course_id

from score_info

where stu_id='001' --001的课程

) and sc.stu_id <> '001' --排除001学生

group by si.stu_id,si.stu_name;

结果如图1-14所示:

📷 图1-14查询至少有一门课与学号为“001”的学生所学课程相同的学生的学号和姓名

(9)如图1-15所示, 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

select

si.stu_name,

ci.course_name,

sc.score,

t1.avg_score

from score_info sc

join student_info si

on sc.stu_id=si.stu_id

join course_info ci

on sc.course_id=ci.course_id

join

(

select

stu_id,

avg(score) avg_score

from score_info

group by stu_id

) t1

on sc.stu_id=t1.stu_id

order by t1.avg_score desc;

结果

📷 图1-15 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩

II