Bootstrap

SQL练习02


title: SQL练习
time: 2019年8月16日16:09:54
tags: SQL


SQL 练习

  1. 查询至少有一门课与学号为“01”的学生所学课程相同的学生的学号和姓名(重点)
SELECT
	s_id,
	s_name 
FROM
	student 
WHERE
	s_id IN (
	SELECT DISTINCT
		s_id 
	FROM
		score 
	WHERE
		c_id IN ( SELECT c_id FROM score WHERE s_id = '01' ) 
	AND s_id != '01' 
	)
  1. 查询和“01”号同学所学课程完全相同的其他同学的学号(重点)
SELECT
	s_id 
FROM
	score 
GROUP BY
	s_id 
HAVING
	count( c_id ) = ( SELECT count( c_id ) FROM score WHERE s_id = '01' ) 
	AND s_id != '01'
  1. 查询没学过"张三"老师讲授的任一门课程的学生姓名(重点,能做出来)
-- 查询没学过"张三"老师讲授的任一门课程的学生姓名 和47题一样(重点,能做出来)
SELECT
	s_name 
FROM
	student 
WHERE
	s_id NOT IN (
	SELECT
		s_id 
	FROM
		score AS s
		INNER JOIN course AS c ON c.c_id = s.c_id
		INNER JOIN teacher AS t ON t.t_id = c.t_id 
	WHERE
	t_name = '张三' 
	)
  1. 查询两门及其以上不及格课程的同学的学号,姓名及其平均成绩(重点)
SELECT
	s.s_id,
	s.s_name,
	a.avg 
FROM
	student AS s
	INNER JOIN ( SELECT s_id, avg( s_score ) AS avg FROM score WHERE s_score < 60 GROUP BY s_id HAVING count( c_id ) >= 2 ) AS a ON s.s_id = a.s_id
  1. 检索"01"课程分数小于60,按分数降序排列的学生信息
SELECT
	s.s_id,
	s.s_name,
	s.s_birth,
	s.s_sex,
	a.s_score 
FROM
	student AS s
	INNER JOIN ( SELECT s_id, s_score FROM score WHERE s_score < 60 AND c_id = '01' ORDER BY s_score DESC ) AS a ON s.s_id = a.s_id
	
  1. 检索"01"课程分数小于60,按分数升序排列的学生信息
SELECT
	s.s_id,
	s.s_name,
	s.s_birth,
	s.s_sex,
	a.s_score 
FROM
	student AS s
	INNER JOIN ( SELECT s_id, s_score FROM score WHERE s_score < 60 AND c_id = '01' ORDER BY s_score ASC ) AS a ON s.s_id = a.s_id
	
  1. 按平均成绩从高到低显示所有学生的所有课程的成绩以及平均成绩(重重点)
-- SQL中的别名 一般不用加双引号和单引号 直接 把别名输入在后边即可,或者加个as
-- 为01,字符值时,也可不用加,如:where name = 李赏 如: where id = 01
SELECT
	s_id 学号,
	max( CASE WHEN c_id = 02 THEN s_score ELSE NULL END )语文,
	min( CASE WHEN c_id = 01 THEN s_score ELSE NULL END ) 数学,
	max( CASE WHEN c_id = 03 THEN s_score ELSE NULL END )英语,
	avg( s_score ) 平均成绩 
FROM
	score 
GROUP BY
	s_id 
ORDER BY
	平均成绩 DESC



  1. 查询各科成绩最高分、最低分和平均分:以如下形式显示:课程ID,课程name,最高分,最低分,平均分,及格率,中等率,优良率,优秀率及格为>=60,中等为:70-80,优良为:80-90,优秀为:>=90 (超级重点)

    select s.c_id 
    , c.c_name
    , MAX(s.s_score) 最高分
    , MIN(s.s_score) 最低分
    , AVG(s.s_score) 平均分
    , SUM(case when s.s_score >= 60 then 1 ELSE 0 END) / COUNT(s.s_id) 及格率
    , SUM(case when s.s_score >= 70 and s.s_score <80 then 1 ELSE 0 END ) / COUNT(s.s_id) 中等率
    , SUM(case when s.s_score >= 80 and s.s_score <90 then 1 ELSE 0 END ) / COUNT(s.s_id) 优良率
    , SUM(case when s.s_score >= 90 then 1 ELSE 0 END ) / COUNT(s.s_id) 优秀率
    
    FROM score as s
    inner JOIN course as c 
    on s.c_id = c.c_id
    GROUP BY c_id
    
  2. 按各科成绩进行排序,并显示排名(重点row_number)

    -- rank() over (partition by ..(按什么分组)(每一组都是从1开始的) order by ..(按什么排序))
    		--> 跳跃式 排序,如:第二名第三名成绩一样,他们排名都是2, 第三名下个直接是4
    -- dense_rank() over (partition by ..(按什么分组) order by ..(按什么排序))
    		--> 连续 排序,如:第二名第三名成绩一样,他们排名都是2, 第三名下个直接是3
    -- row_number() over (partition by ..(按什么分组) order by ..(按什么排序))
    		--> 连续 排序,如:第二名第三名成绩一样,第一个排名是2另一个排名3,, 第三名下个直接是4
    		
    SELECT
    	s_id,
    	c_id,
    	s_score,
    	ROW_number () over ( PARTITION BY c_id ORDER BY s_score DESC ) AS rank 
    FROM
    	score
    
  3. 查询学生的总成绩并进行排名(不重点)

    SELECT
    	s_id,
    	SUM( s_score ) AS 总成绩 
    FROM
    	score 
    GROUP BY
    	s_id 
    ORDER BY
    	总成绩 DESC
    
  4. 查询不同老师所教不同课程平均分从高到低显示(不重点)

    SELECT
    	c_id,
    	AVG( s_score ) 
    FROM
    	score 
    GROUP BY
    	c_id DESC
    
  5. 查询所有课程的成绩第2名到第3名的学生信息及该课程成绩(重要 )

    SELECT
    	s.s_id,
    	st.s_name,
    	st.s_sex,
    	st.s_birth,
    	s.c_id,
    	s.s_score,
    	row_number over ( PARTITION BY c_id ORDER BY s_score DESC ) rank 
    FROM
    	score AS s
    	INNER JOIN student AS st ON st.s_id = s.s_id 
    WHERE
    	s.rank IN ( 2, 3 )
    
  6. 使用分段[100-85],[85-70],[70-60],[<60]来统计各科成绩,分别统计各分数段人数:课程ID和课程名称

    SELECT
    	s.c_id,
    	c.c_name,
    	sum( CASE WHEN s.s_score <= 100 AND s.s_score > 85 THEN 1 ELSE 0 END ) '[100 , 85)',
    	count( CASE WHEN s.s_score <= 85 AND s.s_score > 70 THEN 1 ELSE NULL END ) '[85 , 70)',
    	sum( CASE WHEN s.s_score <= 70 AND s.s_score > 60 THEN 1 ELSE 0 END ) '[70 , 60)',
    	sum( CASE WHEN s.s_score < 60 THEN 1 ELSE 0 END ) '<60' 
    FROM
    	score AS s
    	INNER JOIN course AS c ON s.c_id = c.c_id 
    GROUP BY
    	s.c_id
    
  7. 查询学生平均成绩及其名次(重点)

    SELECT
    	s_id,
    	AVG( s_score ) AS avg,
    	row_number () over ( ORDER BY avg DESC ) 
    FROM
    	score 
    GROUP BY
    	s_id
    
  8. 查询各科成绩前三名的记录(不考虑成绩并列情况)(重点 )

    SELECT
    	c_id,
    	row_number () over ( PARTITION BY c_id ORDER BY s_score DESC ) AS rank 
    FROM
    	score 
    WHERE
    	rank IN ( 1, 2, 3 )
    
  9. 查询每门课程被选修的学生数(不重点)

    SELECT
    	c_id,
    	count( s_id ) 
    FROM
    	score 
    GROUP BY
    	c_id
    
  10. 查询出只有两门课程的全部学生的学号和姓名(不重点)

    -- GROUP BY 不能加where 筛选
    -- 只能有having进行筛选
    
    -- GROUP BY .. having.. 必须在表连接之后进行操作
    SELECT
    	s.s_id,
    	st.s_name,
    	count( s.s_id ) AS cid 
    FROM
    	score AS s
    	INNER JOIN student AS st ON st.s_id = s.s_id 
    GROUP BY
    	s.s_id 
    HAVING
    	cid = 2
    
    

hving进行筛选

-- GROUP BY .. having.. 必须在表连接之后进行操作
SELECT
	s.s_id,
	st.s_name,
	count( s.s_id ) AS cid 
FROM
	score AS s
	INNER JOIN student AS st ON st.s_id = s.s_id 
GROUP BY
	s.s_id 
HAVING
	cid = 2


    

;