**HQL经典练习50题之(一)**

后面25题: https://blog.csdn.net/qq_35954433/article/details/85276223

学生表
create table if not exists t_stu_info(
   stu_id int,
   stu_name string,
   birthday string,
   gender string
   )
   row format delimited
   fields terminated by ' ';

load data local inpath '/home/testdata/stu_info.txt' into table t_stu_info;

01 赵雷 1990-01-01 男
02 钱电 1990-12-21 男
03 孙风 1990-05-20 男
04 李云 1990-08-06 男
05 周梅 1991-12-01 女
06 吴兰 1992-03-01 女
07 郑竹 1989-07-01 女
08 王菊 1990-01-20 女

注!以下两条数据为第30题查询同名同性学生时添加,即前29题的操作数据只有前面8条,
后面的21题产生数据结果才会受到以下两条数据的影响

09 郑竹 1989-07-02 女
10 王菊 1990-02-09 女
课程表
create table if not exists t_course(
stu_id int,
course string,
teach_id int
)
row format delimited
fields terminated by '\t';

load data local inpath '/home/testdata/course.txt' into table t_course;

01      语文    02
02      数学    01
03      英语    03
教师表
create table if not exists t_teach(
teach_id int,
teach_name string
)
row format delimited
fields terminated by '\t';

load data local inpath '/home/testdata/teach_info.txt' into table t_teach;

01      张三
02      李四
03      王五
成绩表
create table if not exists t_score(
stu_id int,
course_id int,
score int
)
row format delimited
fields terminated by '\t';

load data local inpath '/home/testdata/score.txt' into table t_score;

01      01      80
01      02      90
01      03      99
02      01      70
02      02      60
02      03      80
03      01      80
03      02      80
03      03      80
04      01      50
04      02      30
04      03      20
05      01      76
05      02      87
06      01      31
06      03      34
07      02      89
07      03      98.

load表数据时可根据自己的实际数据路径进行导入

~~~~ 数据就位 进入正题 ~~~~

1、 查询"01"课程比"02"课程成绩高的学生的信息及课程分数:

select stu.*,sc.score,a.score
from t_stu_info stu
join t_score sc on sc.course_id = '01' and sc.stu_id = stu.stu_id
left join t_score a on a.course_id = '02' and a.stu_id = stu.stu_id
join t_score b on b.stu_id = stu.stu_id
where sc.score > a.score or a.score is null
group by stu.stu_id,stu.stu_name,stu.birthday,stu.gender,sc.score,a.score
;

运行结果(02课程未考试也算作低于01课程):

2	钱电		1990-12-21	男	70	60
4	李云		1990-08-06	男	50	30
6	吴兰		1992-03-01	女	31	NULL

2、 查询"01"课程比"02"课程成绩低的学生的信息及课程分数:

select stu.*,sc.score,a.score
from t_stu_info stu
full outer join t_score sc on sc.course_id = '01' and sc.stu_id = stu.stu_id
left join t_score a on a.course_id = '02' and a.stu_id = stu.stu_id
join t_score b on b.stu_id = stu.stu_id
where sc.score < a.score or sc.score is null
group by stu.stu_id,stu.stu_name,stu.birthday,stu.gender,sc.score,a.score
;
    
运行结果:
    
1	赵雷		1990-01-01	男	80	90
5	周梅		1991-12-01	女	76	87
7	郑竹		1989-07-01	女	NULL	89

3、 查询平均成绩大于等于60分的同学的学生编号和学生姓名和平均成绩:

select
stu.stu_id,
stu.stu_name,
round(avg(sc.score),2) as avgscore
from t_stu_info stu
join t_score sc on sc.stu_id = stu.stu_id
group by stu.stu_id,stu.stu_name
having round(avg(sc.score),2) >=60
;

运行结果:

1	赵雷		89.67
2	钱电		70.0
3	孙风		80.0
5	周梅		81.5
7	郑竹		93.5

4、查询平均成绩小于60分的同学的学生编号和学生姓名和平均成绩:
(包括有成绩的和无成绩的)

select
stu.stu_id,
stu.stu_name,
round(avg(sc.score),2) as avgscore
from t_stu_info stu
join t_score sc on sc.stu_id = stu.stu_id
group by stu.stu_id,stu.stu_name
having round(avg(sc.score),2) < 60
union all
select 
stu.stu_id,
stu.stu_name,
0 as avgscore
from t_stu_info stu
left join t_score sc on sc.stu_id = stu.stu_id
where sc.score is null
;

运行结果:

8	王菊	0.0
4	李云	33.33
6	吴兰	32.5

5、查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩:

select a.stu_id,a.stu_name,count(a.stu_id),sum(b.score)
from t_stu_info a left join t_score b on a.stu_id=b.stu_id
group by a.stu_id,a.stu_name;

运行结果:

1	赵雷		3	269
2	钱电		3	210
3	孙风		3	240
4	李云		3	100
5	周梅		2	163
6	吴兰		2	65
7	郑竹		2	187
8	王菊		1	NULL

6、查询"李"姓老师的数量:

select teach_name,count(*)
from
t_teach
where teach_name like '李%'
group by teach_name;

运行结果:

李四		1

7、查询学过"张三"老师授课的同学的信息:

答案一:

select a.stu_id,a.stu_name ,a.birthday,a.gender,d.teach_name 
from
t_stu_info a
join t_teach d on d.teach_name='张三'
join t_course c on c.teach_id=d.teach_id
join t_score b on a.stu_id=b.stu_id and b.course_id=c.course_id

运行结果:
 
1	赵雷	1990-01-01	男	张三
2	钱电	1990-12-21	男	张三
3	孙风	1990-05-20	男	张三
4	李云	1990-08-06	男	张三
5	周梅	1991-12-01	女	张三
7	郑竹	1989-07-01	女	张三

答案二(left semi join):

from t_stu_info stu
join t_teach ter on ter.teach_name = '张三'
join t_course cs on ter.teach_id = cs.teach_id 
left semi join t_score sc on sc.stu_id = stu.stu_id and sc.course_id = cs.course_id
;

运行结果:
 
1	赵雷	1990-01-01	男
2	钱电	1990-12-21	男
3	孙风	1990-05-20	男
4	李云	1990-08-06	男
5	周梅	1991-12-01	女
7	郑竹	1989-07-01	女

8、查询没学过"张三"老师授课的同学的信息:

select stu.*,cs.course_id,sc.score
from t_stu_info stu
join t_teach ter on ter.teach_name = '张三'
join t_course cs on ter.teach_id = cs.teach_id 
left join t_score sc on sc.stu_id = stu.stu_id and sc.course_id = cs.course_id
where sc.score is null
;
运行结果:
6	吴兰	1992-03-01	女	2	NULL
8	王菊	1990-01-20	女	2	NULL

9、查询学过编号为"01"并且也学过编号为"02"的课程的同学的信息:

答案一:
select a.stu_id,a.stu_name,a.birthday,a.gender,count(a.stu_id)
from
t_stu_info a left join t_score b on a.stu_id=b.stu_id
where b.course_id in(1,2)
group by a.stu_id,a.stu_id,a.stu_name,a.birthday,a.gender
having count(a.stu_id)>1;

运行结果:

1	赵雷	1990-01-01	男	2
2	钱电	1990-12-21	男	2
3	孙风	1990-05-20	男	2
4	李云	1990-08-06	男	2
5	周梅	1991-12-01	女	2

答案二:

select stu.stu_id,stu.stu_name
from t_stu_info stu
join t_score sc on sc.course_id= '01' and sc.stu_id = stu.stu_id
join t_score sc1 on sc1.course_id= '02' and sc1.stu_id = sc.stu_id
;

运行结果:

1	赵雷
2	钱电
3	孙风
4	李云
5	周梅

10、查询学过编号为"01"但是没有学过编号为"02"的课程的同学的信息:

select stu.stu_id,stu.stu_name
from t_stu_info stu
join t_score sc on sc.course_id= '01' and sc.stu_id = stu.stu_id
left join t_score sc1 on sc1.course_id= '02' and sc1.stu_id = sc.stu_id
where sc1.score is null
;

运行结果:

6	吴兰

11、查询没有学全所有课程的同学的信息:
–先查询出课程的总数量–再查询所需结果

select distinct stu.stu_id,stu.stu_name 
from t_stu_info stu
join t_course cs
left join t_score sc on sc.stu_id = stu.stu_id and cs.course_id = sc.course_id
where sc.score is null
;

运行结果:

5	周梅
6	吴兰
7	郑竹
8	王菊

12、查询至少有一门课与学号为"01"的同学所学相同的同学的信息:

select distinct stu.stu_id,stu.stu_name
from t_stu_info stu
join t_score sc on sc.stu_id = '01'
left join t_score sc1 on sc1.stu_id = stu.stu_id and sc1.course_id = sc.course_id
where stu.stu_id <> '01' and sc1.score is not null
;

运行结果:

2	钱电
3	孙风
4	李云
5	周梅
6	吴兰
7	郑竹

13、查询和"01"号的同学学习的课程完全相同的其他同学的信息:

select *
from
(
select 
a.stu_id,
concat_ws(",",collect_set(cast(a.course_id as string))) as course1
from t_score a
where a.stu_id='1'
group by a.stu_id
) b join
(
select 
c.stu_id,
concat_ws(",",collect_set(cast(c.course_id as string))) as course2
from t_score c
group by c.stu_id
) d on b.course1=d.course2 and d.stu_id<>'1'
;

运行结果:
 
1	1,2,3	2	1,2,3
1	1,2,3	3	1,2,3
1	1,2,3	4	1,2,3

14、查询没学过"张三"老师讲授的任一门课程的学生姓名:

select a.*,sum(d.teach_name)
from
t_stu_info a left join t_score b on a.stu_id=b.stu_id
left join t_course c on c.course_id=b.course_id 
left join t_teach d on c.teach_id=d.teach_id and d.teach_name='张三'
group by a.stu_id,a.stu_name,a.birthday,a.gender
having sum(case when d.teach_name is null then 0 else 1 end)=0
;

运行结果:

6	吴兰	1992-03-01	女	NULL
8	王菊	1990-01-20	女	NULL

15、查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩:

select a.stu_id,a.stu_name,round(avg(b.score),2)
from
t_stu_info a left join t_score b on a.stu_id=b.stu_id
where b.score<60
group by a.stu_id,a.stu_name
having count(a.stu_id)>1;

运行结果:

4	李云		33.33
6	吴兰		32.5

16、检索"01"课程分数小于60,按分数降序排列的学生信息:

select a.*,b.score
from
t_stu_info a left join t_score b on a.stu_id=b.stu_id and b.course_id='1'
where b.score<60
order by b.score desc
;

运行结果:

4	李云	1990-08-06	男	50
6	吴兰	1992-03-01	女	31

17、按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩:

select a.*,b.course_id,b.score,
round(avg(b.score) over(partition by a.stu_id order by b.score desc rows between unbounded preceding and unbounded following),2) as avg 
from
t_stu_info a left join t_score b on a.stu_id=b.stu_id
order by avg desc
;

运行结果:

7	郑竹	1989-07-01	女	2	89	93.5
7	郑竹	1989-07-01	女	3	98	93.5
1	赵雷	1990-01-01	男	3	99	89.67
1	赵雷	1990-01-01	男	2	90	89.67
1	赵雷	1990-01-01	男	1	80	89.67
5	周梅	1991-12-01	女	1	76	81.5
5	周梅	1991-12-01	女	2	87	81.5
3	孙风	1990-05-20	男	1	80	80.0
3	孙风	1990-05-20	男	3	80	80.0
3	孙风	1990-05-20	男	2	80	80.0
2	钱电	1990-12-21	男	2	60	70.0
2	钱电	1990-12-21	男	3	80	70.0
2	钱电	1990-12-21	男	1	70	70.0
4	李云	1990-08-06	男	1	50	33.33
4	李云	1990-08-06	男	3	20	33.33
4	李云	1990-08-06	男	2	30	33.33
6	吴兰	1992-03-01	女	3	34	32.5
6	吴兰	1992-03-01	女	1	31	32.5
8	王菊	1990-01-20	女	NULL	NULL	NULL

18.查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率:

select a.course_id,b.course,
round(max(a.score),2) as maxV,
round(min(a.score),2) as minV,
round(avg(a.score),2) as avgV,
round(sum(case when a.score<60 then 1 else 0 end)/count(1),2) as fail,
round(sum(case when a.score>60 and a.score<=70 then 1 else 0 end)/count(1),2) as pass,
round(sum(case when a.score>70 and a.score<=80 then 1 else 0 end)/count(1),2) as middle,
round(sum(case when a.score>80 and a.score<=90 then 1 else 0 end)/count(1),2) as good,
round(sum(case when a.score>90 and a.score<=100 then 1 else 0 end)/count(1),2) as excellent
from
t_score a left join t_course b on a.course_id=b.course_id
group by a.course_id,b.course
;

运行结果:

1	语文	80	31	64.5		0.33	 0.17 	  0.5	0.0	0.0
2	数学	90	30	72.67		0.17	 0.0	  0.17	0.5	0.0
3	英语	99	20	68.5		0.33	 0.0	  0.33	0.0	0.33

19、按各科成绩进行排序,并显示排名:– row_number() over()分组排序功能

select course_id,score,
row_number() over(partition by course_id order by score)
from
t_score
;

运行结果:

1	31	1
1	50	2
1	70	3
1	76	4
1	80	5
1	80	6
2	30	1
2	60	2
2	80	3
2	87	4
2	89	5
2	90	6
3	20	1
3	34	2
3	80	3
3	80	4
3	98	5
3	99	6

20、查询学生的总成绩并进行排名:

select a.stu_name,
sum(b.score) as total
from
t_stu_info a left join t_score b on a.stu_id=b.stu_id
group by a.stu_name
order by total desc
;

运行结果:

赵雷		269
孙风		240
钱电		210
郑竹		187
周梅		163
李云		100
吴兰		65
王菊		NULL

21、查询不同老师所教不同课程平均分从高到低显示:

select a.teach_name,round(avg(c.score),2)as avg
from
t_teach a left join t_course b on a.teach_id=b.teach_id
left join t_score c on b.course_id=c.course_id
group by a.teach_name
order by avg desc
;

运行结果:

张三		72.67
王五		68.5
李四		64.5

22、查询所有课程的成绩第2名到第3名的学生信息及该课程成绩:

select a.stu_id,a.course_id,b.stu_name,b.birthday,b.gender,a.score,a.rank
from
(
select stu_id,course_id,score,
row_number() over(partition by course_id order by score) as rank
from
t_score
) a join t_stu_info b on a.stu_id=b.stu_id
where a.rank in('2','3')
;

运行结果:

4	1	李云	1990-08-06	男	50	2
2	1	钱电	1990-12-21	男	70	3
2	2	钱电	1990-12-21	男	60	2
3	2	孙风	1990-05-20	男	80	3
6	3	吴兰	1992-03-01	女	34	2
3	3	孙风	1990-05-20	男	80	3

23、统计各科成绩各分数段人数:课程编号,课程名称,[100-85],[85-70],[70-60],[0-60]及所占百分比

select a.course_id,b.course,
sum(case when a.score<60 then 1 else 0 end) as fail,
sum(case when a.score>60 and a.score<=70 then 1 else 0 end) as pass,
sum(case when a.score>70 and a.score<=85 then 1 else 0 end) as good,
sum(case when a.score>85 and a.score<=100 then 1 else 0 end)as excellent,
round(sum(case when a.score<60 then 1 else 0 end)/count(1),2),
round(sum(case when a.score>60 and a.score<=70 then 1 else 0 end)/count(1),2),
round(sum(case when a.score>70 and a.score<=85 then 1 else 0 end)/count(1),2),
round(sum(case when a.score>85 and a.score<=100 then 1 else 0 end)/count(1),2)
from
t_score a left join t_course b on a.course_id=b.course_id
group by a.course_id,b.course
;

运行结果:

1	语文	2	1	3	0	0.33		0.17		0.5		0.0
2	数学	1	0	1	3	0.17		0.0			0.17	0.5
3	英语	2	0	2	2	0.33		0.0			0.33	0.33

24、查询学生平均成绩及其名次:

select a.stu_id,a.avg,
row_number() over(order by avg desc)
from
(
select stu_id,
round(avg(score),2) as avg
from
t_score
group by stu_id
) a
;

运行结果:

7	93.5	1
1	89.67	2
5	81.5	3
3	80.0	4
2	70.0	5
4	33.33	6
6	32.5	7

25、查询各科成绩前三名的记录三个语句

select a.stu_id,a.course_id,a.score,a.rn,a.rk,a.dk
from
(
select *,
row_number() over(partition by stu_id order by score) as rn,
rank() over(partition by stu_id order by score) as rk,
dense_rank() over(partition by stu_id order by score) as dk
from
t_score
) a
where a.rn<4 and a.rk<4 and a.dk<4
;

运行结果:

1	1	80	1	1	1
1	2	90	2	2	2
1	3	99	3	3	3
2	2	60	1	1	1
2	1	70	2	2	2
2	3	80	3	3	3
3	3	80	1	1	1
3	2	80	2	1	1
3	1	80	3	1	1
4	3	20	1	1	1
4	2	30	2	2	2
4	1	50	3	3	3
5	1	76	1	1	1
5	2	87	2	2	2
6	1	31	1	1	1
6	3	34	2	2	2
7	2	89	1	1	1
7	3	98	2	2	2

你可能感兴趣的:(**HQL经典练习50题之(一)**)