GAUSSDB-基础sql查询

举报
yd_294088545 发表于 2026/01/14 10:06:56 2026/01/14
【摘要】 排名函数rank【无并例排名】select * from(select cno,sno,row_number() OVER(partition by cno ORDER BY nvl(score,0) DESC) rumfrom gaussdb.student ) a where rum<=3;【有并例排名】select * from(select cno,sno,rank() OVER...

排名函数rank

【无并例排名】
select * from(
select cno,sno,row_number() OVER(partition by cno ORDER BY nvl(score,0) DESC) rum
from gaussdb.student  
) a where rum<=3;
【有并例排名】
select * from(
select cno,sno,rank() OVER(partition by cno ORDER BY nvl(score,0) DESC) rum
from gaussdb.student  
) a where rum<=3;
【有并例排名,不去重复】
select * from(
select cno,sno,dense_rank() OVER(partition by cno ORDER BY nvl(score,0) DESC) rum
from gaussdb.student  
) a where rum<=3;
【有并例排名,并去重复】
select distinct cno,sno,rum from(
select cno,sno,dense_rank() OVER(partition by cno ORDER BY nvl(score,0) DESC) rum
from gaussdb.student  
) a where rum<=3;

case when 语句

1、查看每门成绩是否大于每门平均成绩
【方法1】
select *,
	case when math <= avg(math) over() then '不大于' else '大于' end as gt_avg_math_flag,
	case when art <= avg(art) over() then '不大于' else '大于' end as gt_avg_art_flag,
	case when phy <= avg(phy) over() then '不大于' else '大于' end as gt_avg_phy_flag
from gaussdb.stu;
【方法2】
select  
,
b.math,
a.avg_math,
case when b.math > a.avg_math then '大于平均成绩' else '不大于平均成绩' end as gt_avg_math_flag,
,
a.avg_art,
case when  > a.avg_art then '大于平均成绩' else '不大于平均成绩' end as gt_avg_art_flag,
b.phy,
a.avg_phy,
case when b.phy > a.avg_phy then '大于平均成绩' else '不大于平均成绩' end as gt_avg_phy_flag  
from (
select  
avg(math) avg_math,
avg(art) avg_art,
avg(phy) avg_phy  
 from gaussdb.stu
) a,gaussdb.stu b

2、id含’3’的同学,求总的绩点,返回绩点最大的ID和总绩点
[0~60) 0绩点,[60~70) 0.1绩点,[70~80) 0.2绩点,[80~90) 0.3绩点,  [90~100] 0.4绩点
【方法1】
select id,  
	(case when math<=59 then 0
	when math<=69 then 0.1
	when math<=79 then 0.2
	when math<=89 then 0.3
	when math<=100 then 0.4 else 0 end)
	+
	(case when art<=59 then 0
	when art<=69 then 0.1
	when art<=79 then 0.2
	when art<=89 then 0.3
	when art<=100 then 0.4 else 0 end)
	+
	(case when phy<=59 then 0
	when phy <=69 then 0.1
	when phy<=79 then 0.2
	when phy<=89 then 0.3
	when phy<=100 then 0.4 else 0 end) as max_jidian  
from gaussdb.stu  where id like '%3%'
order by max_jidian desc limit 1;
【方法2】
SELECT id,p_sum FROM  
(
SELECT id,
 (CASE WHEN math<=59 THEN 0
    WHEN math<=69 THEN 0.1
    WHEN math<=79 THEN 0.2
    WHEN math<=89 THEN 0.3
    WHEN math<=100 THEN 0.4
    ELSE 0
 END )+(
 CASE WHEN art<=59 THEN 0
    WHEN art<=69 THEN 0.1
    WHEN art<=79 THEN 0.2
    WHEN art<=89 THEN 0.3
    WHEN art<=100 THEN 0.4
    ELSE 0
 END)+(
 CASE WHEN phy<=59 THEN 0
    WHEN phy<=69 THEN 0.1
    WHEN phy<=79 THEN 0.2
    WHEN phy<=89 THEN 0.3
    WHEN phy<=100 THEN 0.4
    ELSE 0
 END) AS p_sum,
 DENSE_RANK() OVER(ORDER BY p_sum desc) AS p_rank
FROM gaussdb.stu WHERE id LIKE '%3%'
) WHERE p_rank=1;

3、求总绩点,返回绩点最大的ID和总绩点
【方法1】
select id,  
	(case when math<=59 then 0
	when math<=69 then 0.1
	when math<=79 then 0.2
	when math<=89 then 0.3
	when math<=100 then 0.4 else 0 end)
	+
	(case when art<=59 then 0
	when art<=69 then 0.1
	when art<=79 then 0.2
	when art<=89 then 0.3
	when art<=100 then 0.4 else 0 end)
	+
	(case when phy<=59 then 0
	when phy <=69 then 0.1
	when phy<=79 then 0.2
	when phy<=89 then 0.3
	when phy<=100 then 0.4 else 0 end) as max_jidian  
from gaussdb.stu  order by max_jidian desc limit 1;
【方法2】
SELECT id,p_sum FROM (
SELECT id,
 (CASE WHEN math<=59 THEN 0
    WHEN math<=69 THEN 0.1
    WHEN math<=79 THEN 0.2
    WHEN math<=89 THEN 0.3
    WHEN math<=100 THEN 0.4
    ELSE 0
 END )+(
 CASE WHEN art<=59 THEN 0
    WHEN art<=69 THEN 0.1
    WHEN art<=79 THEN 0.2
    WHEN art<=89 THEN 0.3
    WHEN art<=100 THEN 0.4
    ELSE 0
 END)+(
 CASE WHEN phy<=59 THEN 0
    WHEN phy<=69 THEN 0.1
    WHEN phy<=79 THEN 0.2
    WHEN phy<=89 THEN 0.3
    WHEN phy<=100 THEN 0.4
    ELSE 0
 END) AS p_sum,
 DENSE_RANK() OVER(ORDER BY p_sum desc) AS p_rank
FROM gaussdb.stu ) WHERE p_rank=1;

4、按照总绩点输出
select id,  
	(case when math<=59 then 0
	when math<=69 then 0.1
	when math<=79 then 0.2
	when math<=89 then 0.3
	when math<=100 then 0.4 else 0 end)
	+
	(case when art<=59 then 0
	when art<=69 then 0.1
	when art<=79 then 0.2
	when art<=89 then 0.3
	when art<=100 then 0.4 else 0 end)
	+
	(case when phy<=59 then 0
	when phy <=69 then 0.1
	when phy<=79 then 0.2
	when phy<=89 then 0.3
	when phy<=100 then 0.4 else 0 end) as totaljidian  
from stu;

字符拼接

1、请查询姓名和姓氏,以姓名·姓氏的格式输出,要求首字母大写,姓名和姓氏直接使用”·”拼接
【方法1】
select initcap(firstname ||'·'||fmailyname ) from gaussdb.su;
【方法2】
select initcap(concat(firstname,'·',fmailyname )) from gaussdb.su;

2、插入一条新数据(1,’tom’,’jerry’,’tom’,’H’,63),当出现主键冲突时,将mark改为’F’
id列是PK,不允许重复,下面这个插入失败
insert into gaussdb.su values (1,'tom','jerry','tom','H',63) ;
--下面操作会成功,它并不是插入1条新记录,而是把表中现有的id=1的记录中,mark列的值改为F
insert into gaussdb.su values (1,'tom','jerry','tom','H',63) on duplicate key update mark = 'F';

3、查询表,检查姓名是否是sec开头,展示姓名,判断结果result。
select 
firstname,
case when firstname like 'sec%' then 'True' else 'False' end as result 
from gaussdb.su;

4、查询表中所有列的数据,按照成绩进行排序,并显示名次(position),名次为连续的。要求展示所有字段,名次字段为position。
select * ,dense_rank() over (order by score desc) as postition from gaussdb.su;

join查询

1、求math、phy总成绩以及art、m2的总成绩:
【求每个学生自己的,如果有多条,会分组累加】
SELECT student_id ,sum(math+phy) AS math_phy ,sum(art+m2) AS art_m2 FROM gaussdb.student GROUP BY student_id;
【求每行条记录自己的,如果student_id有重复,不会累加】
SELECT student_id,math+phy AS math_phy,art+m2 AS art_m2  FROM gaussdb.student;
【求所有人总的】
SELECT sum(math+phy) AS math_phy ,sum(art+m2) AS art_m2 FROM gaussdb.student;

2、根据维度表、安装两种加权算法算出每个学生的加权成绩,展示包含student_id,weitht_sum,单个学生加权成绩可以两行输出
【方法1】
SELECT student_id,(s.math*w.math+s.phy*w.phy+*+s.m2*w.m2) AS weitht_sum FROM student s,weight w;
【方法2】
SELECT student_id,s.math*w1.math+s.phy*w1.phy+*+s.m2*w1.m2 as weight_sum FROM student s,weight w1 WHERE w1.weight_no =1
UNION ALL
SELECT student_id,s.math*w2.math+s.phy*w2.phy+*+s.m2*w2.m2 as weight_sum FROM student s,weight w2 WHERE w2.weight_no =2
ORDER BY student_id;

3、根据维度表,安装两种加权算法计算出每个学生的加权成绩,展示包含student_id,weight_sum,单个学生加权成绩要求一行输出
【方法1】
SELECT student_id,
	   s.math*w1.math+s.phy*w1.phy+*+s.m2*w1.m2 AS weitht_sum1, 
	   s.math*w2.math+s.phy*w2.phy+*+s.m2*w2.m2 AS weitht_sum2
FROM student s
inner JOIN weight w1 ON w1.weight_no =1
inner JOIN weight w2 ON w2.weight_no =2;
【方法2】
SELECT student_id,
	   s.math*w1.math+s.phy*w1.phy+*+s.m2*w1.m2 AS weitht_sum1, 
	   s.math*w2.math+s.phy*w2.phy+*+s.m2*w2.m2 AS weitht_sum2
FROM student s,
	(SELECT * FROM weight w WHERE w.weight_no=1 ) AS w1,
	(SELECT * FROM weight w WHERE w.weight_no=2 ) AS w2;

4、对两种加权总成绩进行排序。要求输出格式student_id,weight_sum、rank1、weight2_sum、rank2
【方法1】
SELECT student_id,
	   s.math*w1.math+s.phy*w1.phy+*+s.m2*w1.m2 AS weitht_sum1, 
	   dense_rank() OVER(ORDER BY weitht_sum1 DESC ) AS rank1,
	   s.math*w2.math+s.phy*w2.phy+*+s.m2*w2.m2 AS weitht_sum2,
	   dense_rank() OVER(ORDER BY weitht_sum2 DESC ) AS rank2
FROM student s
inner JOIN weight w1 ON w1.weight_no =1
inner JOIN weight w2 ON w2.weight_no =2;
【方法2】
SELECT student_id,
	   s.math*w1.math+s.phy*w1.phy+*+s.m2*w1.m2 AS weitht_sum1, 
	   dense_rank() OVER(ORDER BY weitht_sum1 DESC ) AS rank1,
	   s.math*w2.math+s.phy*w2.phy+*+s.m2*w2.m2 AS weitht_sum2,
	   dense_rank() OVER(ORDER BY weitht_sum2 DESC ) AS rank2
FROM student s,
	(SELECT * FROM weight w WHERE w.weight_no=1 ) AS w1,
	(SELECT * FROM weight w WHERE w.weight_no=2 ) AS w2;

查询分组 group by

2、由于每栋楼各个年龄段的人都有,故按age年龄段分组[0-18),[18-35),[35-55),[55-maxvalues)形成age_group,每个组命名group1,group2,group3,group4
select * , 
	case
		when age<18 then 'group1'
		when age >= 18 and age<35 then 'group2'
		when age >= 35 and age<55 then 'group3'
		else 'group4'
	end as age_group
from residents;

3、age_group按每组人数多少排序,查询出age_group、人数、最大年龄、最小年龄、平均年龄(平均年龄向下取整)
【方法1】
SELECT ag.age_group,
	   count(*) AS '人数',
	   max(ag.age) AS '最大年龄',
	   min(ag.age) AS '最小年龄',
	   floor(avg(ag.age)) AS '平均年龄'
FROM 
(
SELECT age,sex,building,CASE 
	WHEN r.age<18 THEN 'group1'
	WHEN r.age<35 THEN 'group2'
	WHEN r.age<55 THEN 'group3'
	WHEN r.age>=55 THEN 'group4'
END AS age_group
FROM RESIDENTS r ) AS ag GROUP BY age_group;
【方法2】
select
	case
		when age<18 then 'group1'
		when age >= 18 and age<35 then 'group2'
		when age >= 35 and age<55 then 'group3'
		else 'group4'
	end as age_group,
	count(*) as "人数",
	max(age) as "最大年龄",
	min(age) as "最小年龄",
	floor(avg(age)) as "平均年龄"
from residents
group by age_group
order by "人数" desc;

4、由于需要每天要送食物,增加如下每个年龄段所需食物营养价值表,需要统计出该小区每天总营养值
select
	sum(
	case 
		when age<18 then 5 
		when age >= 18 and age<35 then 7 
		when age >= 35 and age<55 then 6
	else 5 end
	) as "每天总营养值"
from
	residents;
【如果需要计算每个人需要的总营养值如下】
select age,
	case
		when age<18 then 'group1'
		when age >= 18 and age<35 then 'group2'
		when age >= 35 and age<55 then 'group3'
		else 'group4'
	end as age_group,
	case
		when age_group = 'group1' then 5
		when age_group = 'group2' then 7
		when age_group = 'group3' then 6
		when age_group = 'group4' then 5
	end as nutrition_value
from
	residents;
	
5、按楼栋求出每栋楼所需营养值
select building,
	sum(
	case 
		when age<18 then 5
		when age >= 18 and age<35 then 7
		when age >= 35 and age<55 then 6
		else 5 end
	) as "每栋楼所需营养价值"
from residents
group by building;

查询平均值比较等

1、输出每月月考总分都比学号为5的同学分数高的所有学生信息。
【方法1】
select a.* 
from student a, (select month, score from student where sno=5) b 
where a.month=b.month and coalesce(a.score,0) > coalesce(b.score,0) and a.sno<>5;
【方法2】
select a.* 
from student a 
inner join (select month,nvl(score,0) as fscore from student where sno=5) b 
on a.month=b.month 
where nvl(a.score,0) > b.fscore and a.sno <>5;
【方法3】
select a.* 
from student a,
(select month,nvl(score,0) as fscore from student where sno=5) b 
where a.month=b.month and nvl(a.score,0) > b.fscore and a.sno <>5;
【方法4】
with temp as (select month,nvl(score,0) as nscore from student where sno=5)
select s.* 
from student s 
inner join temp t on t.month=s.month 
where nvl(s.score,0) > nscore and sno<>5;
【方法5】
select sno,sname,t1.month,allscore 
from 
(select month,sno,sname,sum(nvl(score,0)) allscore from student group by month,sno,sname) t1  
join  (select month,sum(nvl(score,0)) allscore2  from student where sno=5 group by month) t2 on t1.month=t2.month 
where allscore>allscore2 
order by sno;
【方法6】
SELECT DISTINCT sno,sname,cno 
FROM student sst 
WHERE sst.sno  NOT IN 
(
	SELECT s.sno FROM student s LEFT JOIN 
	(
		SELECT * FROM  student t WHERE t.sno =5
	) AS st_5 ON s.MONTH=st_5.MONTH WHERE NVL(st_5.score,0)>=NVL(s.score,0)
);
【方法7】
SELECT DISTINCT s1.sno, s1.sname, s1.cno
FROM student s1
WHERE s1.sno NOT IN (
    SELECT s1.sno
    FROM student s1
    JOIN student s2
      ON s2.sno = 5 AND s1.month = s2.month
    WHERE nvl(s1.score, 0) <= nvl(s2.score, 0)
);

2、输出每次月考缺考的学生信息,要求打印姓名、班级编号和缺考次数。
select month,sname,cno,count(*) AS "缺考次数" from student where score is null group by month,sname,cno;

3、输出每次月考都和Tom同时缺考的所有学生信息,要求打印学号、姓名和月考总分。
【方法1】
select sno,sname,sum(nvl(score,0)) as total_score 
from student 
where sno in 
(
select a.sno from student a 
	inner join (select sno,month from student where sname='Tom' and score is null) b 
	on a.month=b.month and a.sno <> b.sno 
	where a.score is null
	) 
group by sno,sname;
【方法2】
select sno,sname,sum(nvl(score, 0)) as total_score
from student
where (sno,sname) in 
(
select sno,sname from student
	where month in (select month from student where sname = 'Tom' and score is null)
		and score is null
		and sname <> 'Tom'
)
group by sno,sname;
【方法3】
select s.sno,s.sname,sum(nvl(score,0)) as total_score 
from student s
where sno in 
(
select a.sno from student a,
		(select sno,month from student where sname = 'Tom' and score is null) b
	where
		a.month = b.month
		and a.sno <> b.sno
		and a.score is null
) 
group by s.sno,s.sname;

4、输出全校月考中位数分数。
【方法1】   
--GaussDB主备版支持median函数,分布式版不支持
select median(nvl(score,0)) from student;
【方法2】
select
	round(avg(score),2)
from
(
  select score,count(*) over() as count,row_number () over (order by nvl(score,0)) as rowno from student
)
where
	case
		when count%2 = 0 then rowno = count / 2 or rowno = count / 2 + 1
		else rowno =(count + 1)/ 2
	end;
【方法3】
select
	round(avg(score),0)
from
(
	select score from student
	order by nvl(score,0)
	limit (select ceil(count(*)/2) from student),
	case
		when (select count(*)%2 from student)= 0 then 2
		else 1
	end
);
【方法4】
SELECT avg(NVL(score,0))
FROM (
    SELECT score,
           ROW_NUMBER() OVER (ORDER BY NVL(score,0)) AS row_num,
           COUNT(*) OVER () AS total_count
    FROM student
) AS ranked_scores
WHERE row_num in (floor((ranked_scores.total_count+1)/2),floor((ranked_scores.total_count+2)/2));
【方法5】
按月分组统计
with temp as 
(
select month,
	nvl(score,0) as nscore,
	row_number() over(partition by month order by nscore) as rn,
	count(*) over(partition by month) as cn
from
	student
)
select
	month,
	avg(nscore) as avg_score
from temp
where
	(case
		when cn%2 = 1 then rn =(cn + 1)/ 2
		else rn = cn / 2 or rn = cn / 2 + 1
	end)
group by month;
【方法6】
按月分组统计
select month,avg(mscore) as medianscore
from
	(select month,mscore
	from
		(select month,
			nvl(score,0) as mscore,
			row_number() over(partition by month order by mscore) as cn,
			count(*) over(partition by month) as scount
		from
			student) a
	where
		case
			when scount%2 = 0 then (cn = scount / 2 or cn = scount / 2 + 1)
			else cn =(scount + 1)/ 2
		end ) b
group by month;
【方法7】
按月分组统计
SELECT month,avg(monthly_score) as median_score 
FROM (
	SELECT month,monthly_score
	FROM  (
		SELECT month, sno, COALESCE(score, 0) monthly_score,
			   ROW_NUMBER() OVER (PARTITION BY month ORDER BY monthly_score) AS row_num,
			   COUNT(*) OVER (PARTITION BY month) AS total_students
		FROM student
		)
	WHERE row_num = FLOOR(total_students / 2) + 1 OR row_num = FLOOR((total_students + 1) / 2)
)
GROUP BY month;

5、统计每个班每次月考的最高分数,要求打印班级名称,考试时间和月考分数。
【方法1】
select cname,month,max(nvl(score,0)) 
from student,class 
where student.cno=class.cno
group by cname,month 
order by cname,month;
【方法2】
select cname,month,max(nvl(score,0)) as max_score 
from student s inner join class c on c.cno = s.cno 
group by cname,month 
order by cname,month;
【方法3】
select
	a.cname,a.month,a.score
from
	(
	select
		cname,
		month,
		score,
		rank() over (partition by s.cno,month order by coalesce(score,0) desc) as ranking
	from
		student s join class c on s.cno = c.cno 
) a
where a.ranking = 1;
【注意】:要考虑到NULL值的影响, 统计数据时应该将其视为0

6、查看每个班级(cno)月考总分(score)前三名,其中要求分数相同的人具有相同的编号
【方法1】
select * from
(
	select *,rank() over(partition by cno order by nvl(score,0) desc) as rn
	from student
)
where rn <= 3;
【方法2】
select * from
(
	select *,dense_rank() over(partition by cno order by nvl(score,0) desc) as drk
	from student
)
where drk <= 3;

其他示例

1、输出class1班级中比class2班级每月月考最低分还低的学生信息,要求打印学号、姓名和月考总分。
select sno,sname,score from student s
inner join 
class c on c.cno = s.cno
inner join 
(
select month,min(score) as minscore from student s
	inner join class c on c.cno = s.cno
	where c.cname = 'class2'
	group by month
) s2 
on s.month = s2.month
where c.cname = 'class1' and score < s2.minscore;

2、打印月考总分平均分最高的学生信息,输出学号,姓名和月考总分平均分。
【方法1】
select sno,sname,avg(COALESCE(score, 0)) as avg_score 
from student 
group by sno,sname 
order by avg_score desc limit 1;
【方法2】
select sno,sname,avgscore
from
	(select sno,sname,
		avg(nvl(score, 0)) as avgscore,rank() over(order by avgscore desc) as rank
	from student
	group by sno,sname) s
where rank = 1;

3、输出每个学生月考平均分和最高月考平均分学生之间的分数差距,打印学号、姓名、月考平均分和差距分数。
【方法1】
select
	sno,
	sname,
	avgscore,
	maxscore-avgscore as diffscore
from
	(select
		sno,
		sname,
		round(avg(nvl(score, 0)),2) as avgscore,
		max(avgscore) over() as maxscore
	from student
	group by sno,sname) t;
【方法2】
select sno,sname,
	round(avg(nvl(score, 0)),2) avgscore,
(
	select max(avgscore)
	from
		(select round(avg(nvl(score, 0)),2) avgscore from student group by sno)
)-avgscore m_score
from student
group by sno,sname;
【方法3】
SELECT sno,sname,avg(NVL(s.score,0)),
(select avgscore
	from
	(
	select sno,sname,
		avg(nvl(score, 0)) as avgscore,rank() over(order by avgscore desc) as rank
	from student
	group by sno,sname
	) s
where rank = 1
)-avg(NVL(s.score,0)) AS '分数差' 
FROM student s GROUP BY s.sno,s.sname

1、求各科分数是否大于平均分
SELECT student_id,
	   CASE WHEN g.math> avg(NVL(g.math,0)) over() THEN 't' ELSE 'f'END AS math ,
	   CASE WHEN g.phy> avg(NVL(g.phy,0)) over() THEN 't' ELSE 'f'END AS phy ,
	   CASE WHEN g.music> avg(NVL(g.music,0)) over() THEN 't' ELSE 'f'END AS music ,
	   CASE WHEN g.art> avg(NVL(g.art,0)) over() THEN 't' ELSE 'f'END AS art
FROM grades g;

2、求学号含3的学生的平均成绩,打印平均成绩最高的学号和平均成绩    
select student_id,avg_score from (
select *,
(nvl(math,0)+nvl(phy,0)+nvl(music,0)+nvl(art,0))/4 avg_score,
row_number() over(order by avg_score desc) rn
from grades where student_id like '%3%'
) where rn=1;

3、求总绩点并按绩点排名
select student_id,
(case 
	when nvl(math,0)<60 then 0
	when nvl(math,0)<70 then 0.1
	when nvl(math,0)<80 then 0.2
	when nvl(math,0)<90 then 0.3
	else 0.4 end 
+
case 
	when nvl(phy,0)<60 then 0
	when nvl(phy,0)<70 then 0.1
	when nvl(phy,0)<80 then 0.2
	when nvl(phy,0)<90 then 0.3
	else 0.4 end 	
+
case 
	when nvl(music,0)<60 then 0
	when nvl(music,0)<70 then 0.1
	when nvl(music,0)<80 then 0.2
	when nvl(music,0)<90 then 0.3
	else 0.4 end 
+
case 
	when nvl(art,0)<60 then 0
	when nvl(art,0)<70 then 0.1
	when nvl(art,0)<80 then 0.2
	when nvl(art,0)<90 then 0.3
	else 0.4 end 
) as total_point 
from grades 
order by total_point desc;




1、对学习math和pysical排名前十的学生,art加5分,求所有学生总成绩
【方法1】
with stu as 
(
select
	distinct student_id
from
	(
	select
		student_id,
		math + pysical as total_score,
		rank() over(order by total_score desc) as rk
	from student)
where
	rk <= 10
)
select
	student_id,
	sum(math + pysical + arts + music)
from
(
	select
		s.student_id,
		math,
		pysical,
		case
			when s.student_id = stu.student_id then art + 5
			else art
		end as arts,
		music
	from
		student s left join stu on stu.student_id = s.student_id
) group by student_id; 
【方法2】
select
	student_id,
	sum(nmath + npysical + arts + nmusic) as tscore
from
(
	select
		s.student_id,
		nvl(math,0) as nmath,
		nvl(pysical,0) as npysical,
		case
			when s.student_id = mp.student_id then nvl(art,0)+ 5
			else nvl(art,0)
		end as arts,
		nvl(music,0) as nmusic
	from
		student s left join 
	(
		select distinct student_id
		from
			(
				select
					student_id,
					nvl(math,0)+ nvl(pysical,0) as mpscore,
					row_number() over(order by mpscore desc) as rn
				from student
			) where rn <= 10
	) mp on s.student_id = mp.student_id
) group by student_id;

【方法3】
--每个学生sum(math+pysical)之和是前10的学生,每行记录art都+5
SELECT student_id,
sum(NVL(math,0)+NVL(pysical,0)+NVL(music,0)+NVL(art_5,0)) 
FROM 
( 
	SELECT *,
		CASE 
		WHEN s.student_id IN 
		(
			SELECT DISTINCT student_id FROM 
			(
				SELECT student_id,
				sum(s.math+s.pysical) AS sum_mp,
				DENSE_RANK() OVER(ORDER BY sum_mp DESC ) AS rank  
				FROM student s GROUP BY s.student_id
			) mp_id WHERE mp_id.rank<=10
		) THEN NVL(,0)+5
		ELSE nvl(,0)
		END AS art_5
	FROM  student s
) AS aa GROUP BY student_id;

【方法4】
--math与和pysical之和是前10的记录,前10中的每行记录art都+5
select student_id,
sum(case 
	when rn<=10 then math+pysical+art+music+5
else math+pysical+art+music
end) total_score from 
(
select 
*,
row_number() over(order by (math+pysical) desc) rn 
from student 
) ss
group by student_id

2、获取art和music排名前十,同时math和pysical在art和music前十名的学生信息
【方法1】
--不考虑排名并列
select s1.*,s2.mscore
from 
(
	select *,(art + music) ascore from student order by ascore desc limit 10
) s1 join 
(
select *,(math + pysical) mscore from student order by mscore desc limit 10
) s2 
on s1.student_id = s2.student_id;

【方法2】
--考虑排名并列
select
	distinct s.*
from
student s 
inner join 
(
	select student_id from 
		(
			select
				student_id,
				nvl(math,0)+ nvl(pysical,0) as mpscore,
				row_number() over(order by mpscore desc) as rn
			from student
		)
		where rn <= 10
) mp on s.student_id = mp.student_id
inner join 
(
	select student_id from 
		(
			select
				student_id,
				nvl(art,0)+ nvl(music,0) as mpscore,
				row_number() over(order by mpscore desc) as rn
			from student
		)
	where rn <= 10
) am on s.student_id = am.student_id
order by student_id;

【方法3】
--每个学生sum(math+pysical)之和是前10的学生,同时 每个学生sum(art+music)之和是前10的学生
SELECT distinct s.* 
FROM student s 
WHERE s.student_id IN 
(
	SELECT a.student_id FROM 
	(
		SELECT DISTINCT student_id FROM 
		(
			SELECT student_id,
				   sum(NVL(,0)+NVL(s.music,0)) AS sum_am,
				   DENSE_RANK() OVER(ORDER BY sum_am DESC ) AS rank  
			FROM student s GROUP BY s.student_id
		) am_id WHERE am_id.rank<=10 
	) a inner JOIN 
	(
		SELECT DISTINCT student_id FROM 
		(
			SELECT student_id,
				   sum(NVL(s.math,0)+NVL(s.pysical,0)) AS sum_mp,
				   DENSE_RANK() OVER(ORDER BY sum_mp DESC ) AS rank  
			FROM student s GROUP BY s.student_id
		) mp_id WHERE mp_id.rank<=10
	) b ON a.student_id=b.student_id
);

【方法4】
--math与和pysical之和是前10的记录,同时 art与和music之和是前10的记录
select s1.student_id,s1.math,s1.pysical,,s1.music from 
(select 
*,
row_number() over(order by (math+pysical) desc) rn 
from student 
) s1 ,
(
select 
*,
row_number() over(order by (art+music) desc) rn 
from student 
) s2 
where s1.student_id=s2.student_id and s1.rn<=10 and s2.rn<=10


2、查询202202班级同一科目成绩比202201班级最高分高的同学
【方法1】
select * from test t1 where t1.class=202202 and grade >
(
	select max(grade) from test t2 
	where t2.class=202201 and t2.kemu=t1.kemu
);
【方法2】
select * from test t1 join 
(
	select kemu,max(grade) as t2_max_grade
	from test 
	where class = 202201
	group by kemu
) t2 
on t1.kemu = t2.kemu
and t1.grade > t2.t2_max_grade
and t1. class = 202202;


1、查202201班级和202202班级所有人语文成绩前10的记录,第一个查询要使用union
【方法1】
select * from 
(
	select * from score1 where kemu='chinese' 
	union 
	select * from score2 where kemu='chinese'
) t order by Grade desc limit 10;
【方法2】
select * from 
(
	select *,row_number() over(order by Grade desc) rn from 
	(
		select * from score1 where kemu='chinese' 
		union 
		select * from score2 where kemu='chinese'
	)
) t where rn<=10;
【方法3】
select * from 
(
	select *,rank() over(order by Grade desc) rn from 
	(
		select * from score1 where kemu='chinese' 
		union 
		select * from score2 where kemu='chinese'
	)
) t where rn<=10;
【方法4】
select * from 
(
	select *,dense_rank() over(order by Grade desc) rn from 
	(
		select * from score1 where kemu='chinese' 
		union 
		select * from score2 where kemu='chinese'
	)
) t where rn<=10;

2、查看两个班级相同的科目,202201班在score2中不存在的成绩,要求使用not in
【判断某一科目】
select * from score1 where kemu='chinese' and grade not in (select grade from score2 where kemu='chinese');
【判断所有科目】
select * from score1 s1 where grade not in (select grade from score2 s2 where s2.kemu=s1.kemu);

3、对以上SQL语句进行改写为not exits
【判断某一科目】
select * from score1 t1 where t1.kemu='chinese' and  not exists (select grade from score2 t2 where t2.kemu='chinese' and t1.grade=t2.grade) ;
【判断所有科目】
select * from score1 t1 where not exists (select grade from score2 t2 where t2.kemu=t1.kemu and t1.grade=t2.grade);

4、查询202201班级的学生的成绩比202202班级的学生最高成绩还要大的学生信息
【方法1】
select sno ,totalscore1
from
	(select sno ,Grade as totalscore1 from score1) s1,
	(select max(Grade) as totalscore2 from score2) s2
where totalscore1>totalscore2;
【方法2】
select * from score1 where Grade>(
select max(Grade) as totalscore2 from score2
);

1、查询2020学年,语文的平均成绩大于80的班级,打印班级名称及平均成绩,要求where条件里有两个非相关子查询
【方法1】
select c_name,
	avg(score) as avgscore
from scclassore s,
	class c
where s.cno = c.cno
	and course_no in (select course_no from course where course_name = '语文')
	and s.cno in (select cno from class where xuenian = '2020')
group by c_name
having avgscore >80;
【方法2】
select c.c_name,
	avg(s.score) as avg_score
from scclassore s
inner join class c 
on c.cno = s.cno
where s.cno in (select cno from class where xuenian = '2020')
	and s.course_no in (select course_no from course where course_name = '语文')
group by c.c_name
having avg_score>80;

2、优化上一步的语句,将where条件中的非相关子查询 改为from后边的范围表
【方法1】
select c_name ,avg(score) avg_score
from scclassore ss,
(select cno,c_name from class where xuenian='2020') cl,
(select course_no from course where course_name='语文') co 
where cl.cno=ss.cno and ss.course_no =co.course_no
group by c_name 
having avg_score>80
【方法2】
select c_name,avg_score
from class t3 ,
(
	select t1.cno,avg(t1.score) as avg_score
	from scclassore t1
	where
		t1.course_no in (select course_no from course t2 where t2.course_name = '语文')
		and t1.cno in (select cno from class where xuenian = '2020')
	group by t1.cno 
	having avg_score>80
) t4 
where t3.cno = t4.cno;
【方法3】
select e.c_name,d.avg
from class e,
(
	select t1.cno,avg(t1.score) avg
	from scclassore t1,course t2,
	(select cno from class where xuenian = '2020') t3,
	(select course_no from course where course_name = '语文') t4
	where t1.course_no = t2.course_no
		and t1.cno = t3.cno
		and t2.course_no = t4.course_no
	group by t1.cno
	having avg(t1.score)>80
) d 
where e.cno = d.cno;

3、优化上一步的语句,将from后边的子查询优化为父表的关联查询
【方法1】
select
	c_name,
	avg(score) as avgscore
from
	scclassore s,
	class c,
	course cs
where
	s.cno = c.cno
	and s.course_no = cs.course_no
	and course_name = '语文'
	and xuenian = '2020'
group by c_name
having avgscore >80;
【方法2】
select
	c_name,
	avg(score) as avgscore
from scclassore s
inner join class c on s.cno = c.cno
inner join course cs on s.course_no = cs.course_no
where course_name = '语文' and xuenian = '2020'
group by c_name
having avgscore >80;

1、查找202401班同科目的分数不在202402班级中,显示202401班级的所有成绩信息
【方法1】
select * from score1 s1 where grade not in (
select grade from score1 s2 where s1.course_name=s2.course_name 
)
【方法2】
select s1.* from score1 s1,student st 
where s1.student_id=st.student_id and st.cno=202401 and s1.grade not in (
	select grade
	from score2 s2,student st 
	where s2.student_id=st.student_id and st.cno=202402 and s1.course_name = s2.course_name);

2、在不改变上题结果的情况下,对sql进行改写
select s1.* from score1 s1,student st 
where s1.student_id=st.student_id and st.cno=202401 and not exists (
	select grade
	from score2 s2,student st 
	where s2.student_id=st.student_id and st.cno=202402 and s1.course_name = s2.course_name and s1.grade = s2.grade);
【声明】本内容来自华为云开发者社区博主,不代表华为云及华为云开发者社区的观点和立场。转载时必须标注文章的来源(华为云社区)、文章链接、文章作者等基本信息,否则作者和本社区有权追究责任。如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。