MySQL实验三:查询练习

MySQL实验三:查询练习

目录

目录


在这里插入图片描述

前言

整理实验的查询练习题,数据库表会提供建立的sql语句,个人整理版非官方,如果有错误或者疑问,欢迎在评论区提出见解!

需要准备的工具:

  1. Navicat9以上
  2. mysql5.7或者mysql8都可以

在这里插入图片描述

sql文件

阿里云盘里包含了db_student和studymysql的表。

https://www.aliyundrive.com/s/47dHZqRHef9

提取码: od26

实验目的

  1. 掌握查询语句的基本组成和使用方法。
  2. 掌握常见的查询技巧。

实验预习

1、 SQL中查询语句的语句格式:

SELECT column_name,column_name FROM table_name;

2、SQL中创建数据表的语句格式:

 CREATE TABLE table_name (column_name1 data_type(size),column_name2 data_type(size),column_name3 data_type(size), .... );

column_name 参数规定表中列的名称。

data_type 参数规定列的数据类型(例如 varchar、integer、decimal、date 等等)。

size 参数规定表中列的最大长度。

实验内容及要求

1、数据库**db_student**中基本表的数据如下,输入下列数据。

学生表:Student

SnoSnameSsexSageSdept
9512101李勇19计算机系
9512103王敏20计算机系
9521101张莉22信息系
9521102吴宾21信息系
9521103张海20信息系
9531101钱小平18数学系
9531102王大力19数学系

课程表:Course

CnoCnameCcreditSemsterPeriod
C01计算机导论313
C02VB434
C03计算机网络474
C04数据库基础664
C05高等数学818

选课表:SC

SnoCnoGrade
9512101C0395
9512103C0351
9512101C0580
9512103C05NULL
9521101C05NULL
9521102C0580
9521103C0545
9531101C0581
9531101C0167
9531102C0594
9521103C0180
9512101C01NULL
9531102C01NULL
9512101C0287
9512101C0476

2、根据db_student中的数据,完成下列查询,将查询语句写在下方。

1)查询全体学生的信息

Select * from student;

2)查询“信息系”学生的学号,姓名和出生年份。

Select sno,sname,YEAR(NOW())-sage from student 

WHERE sdept='信息系';

3)查询考试不及格的学生的学号。

Select distinct sno from sc where grade<60;

4)查询无考试成绩的学生的学号和相应的课程号

Select sno,cno from sc where grade is null;

5)将学生按年龄升序排序。

Select * from student order by sage;

6)查询选修了课程的学生的学号和姓名。

(要求:分别使用连接查询、嵌套子查询完成)

连接查询:
SELECT distinct student.Sno, Sname

FROM student

INNER JOIN sc ON student.Sno = sc.Sno;

这里使用了INNER JOIN连接了student和sc表,通过Sno字段将两个表关联起来,然后选择出Sno和Sname两个字段。

嵌套子查询:
SELECT Sno, Sname

FROM student

WHERE Sno IN (

  SELECT DISTINCT Sno

  FROM sc

);

这里使用了IN子句和嵌套子查询,首先在子查询中获取所有选过课程的学生学号(使用DISTINCT关键字去重),然后在外层查询中选择出学号和姓名两个字段。

7)查询年龄在20-23岁之间的学生的系,姓名,年龄,按照系升序排序。

Select sname,sage,sdept from student where sage between 20 and 23 order by sdept;

8)查询选修了“计算机网络”或者“数据库基础”课程的学生的学号,姓名。

连接查询:
SELECT student.Sno, Sname
FROM student
INNER JOIN sc ON student.Sno = sc.Sno
INNER JOIN course ON sc.Cno = course.Cno
WHERE Cname IN ('计算机网络', '数据库基础');

这里使用了INNER JOIN连接了student、sc和course表,通过Sno和Cno字段将三个表关联起来,然后使用WHERE子句过滤出选修了“计算机网络”或者“数据库基础”课程的选课记录,最后选择出Sno和Sname两个字段。

嵌套子查询:
SELECT Sno, Sname
FROM student
WHERE Sno IN (
    SELECT DISTINCT Sno
    FROM sc
    WHERE Cno IN (
        SELECT Cno
        FROM course
        WHERE Cname IN ('计算机网络', '数据库基础')
    )
);

这里使用了嵌套子查询,首先在最内层子查询中获取课程名为“计算机网络”或者“数据库基础”的课程号,然后在中间层子查询中获取选修了这些课程的学生学号(使用DISTINCT关键字去重),最后在外层查询中选择出学号和姓名两个字段。

9)查询姓“张”的学生的基本信息。

select * from student where sname like'张%';

10)查询学生的选课情况,要求输出学号,姓名,课程门数,课程名列表(用逗号分隔),按照学号升序排序。

SELECT student.Sno, Sname, COUNT(sc.Cno) AS CourseCount, GROUP_CONCAT(course.Cname SEPARATOR ', ') AS CourseList
FROM student
LEFT JOIN sc ON student.Sno = sc.Sno
LEFT JOIN course ON sc.Cno = course.Cno
GROUP BY student.Sno
ORDER BY student.Sno ASC;

需要注意的是MySQL的版本中启用了ONLY_FULL_GROUP_BY模式,该模式要求SELECT语句中的非聚合列必须在GROUP BY子句中出现。换句话说,如果SELECT语句中包含非聚合列,那么这些列必须在GROUP BY子句中列出。

可以通过修改MySQL的配置文件或者执行如下SQL语句来关闭ONLY_FULL_GROUP_BY模式:

SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

需要先运行这行代码再查询,否则会报错。

11)查询选修了课程的学生的总人数。

SELECT count(DISTINCT sno) FROM sc WHERE sno in (select sno from sc);

12)统计各门课程选修人数,要求输出课程代号,课程名,选修人数,有成绩人数(grade不为NULL),最高分,最低分,平均分,按课程号排序。

Select c.cno,cname,count(*),MAX(grade),MIN(grade),AVG(grade),COUNT(grade)

From student s,sc,course c where s.sno=sc.sno and sc.cno=c.cno GROUP BY c.cno

order by cno;

13)统计各门课程的重修人数(包括grade为NULL),要求输出课程代号,重修人数。

SELECT cno,COUNT(*) from sc WHERE grade<60 OR grade is NULL GROUP BY cno;

14)查询选修通过2门(包括2门)以上的学生的信息,输出学号、选修通过门数、平均成绩,按门数降序排序,若门数相同,按照成绩降序。

select sno, count(*),avg(grade)

from sc  where grade >= 60

group by sno

having count(*) >= 2 order by count(*) DESC,avg(grade) desc;

15)查询与“王大力”同一个系的学生的基本信息。

SELECT * FROM student WHERE sname !='王大力' and sdept in (

SELECT distinct sdept FROM student WHERE sname='王大力');

16)查询每个学生高于他自己选修平均分的那门课程的成绩,输出学号,课程号,课程成绩,他所有课程的平均分,并按学号升序排列。

(要求:使用基于子查询派生表的查询方法)

SELECT sc.sno,cno,grade, avggrade FROM sc,

(SELECT sno, AVG(grade) avggrade FROM sc GROUP BY sno) AS  avg_sc

WHERE sc.sno=avg_sc.sno AND

sc.grade>avg_sc.avggrade

ORDER BY sc.sno;

通过将子查询的结果作为临时表(派生表)来进行进一步的查询操作。

17)查询没有同时选修“计算机导论”和“计算机网络”两门课的学生的学号,姓名。

SELECT sno, sname 
FROM student 
WHERE sno NOT IN (
  SELECT sno 
  FROM sc 
  WHERE cno IN (
    SELECT cno 
    FROM course 
    WHERE cname IN ('计算机导论', '计算机网络')
  )
  GROUP BY sno
  HAVING COUNT(DISTINCT cno) = 2
);

这个SQL语句使用了三个子查询:

  • 最内层的子查询 SELECT cno FROM course WHERE cname IN ('计算机导论', '计算机网络') 查询出了“计算机导论”和“计算机网络”两门课程的课程号。
  • 中间层的子查询 SELECT sno FROM sc WHERE cno IN (...) GROUP BY sno HAVING COUNT(DISTINCT cno) = 2 查询出了同时选修了这两门课程的学生的学号。这里使用了GROUP BY子句和HAVING子句,分别对学生的选课记录按学号分组,然后筛选出选修的课程数为2的学生,即同时选修了“计算机导论”和“计算机网络”两门课程的学生。
  • 最外层的查询 SELECT sno, sname FROM student WHERE sno NOT IN (...) 选择出没有选修这两门课程的学生的学号和姓名。这里使用NOT IN子句来排除已经在中间层查询中被筛选出的学生。

本题同样可以用not exits来写,思路一致。

Select sno,sname from student where sno not in (select sno from student where not exists(

Select * from course where cname in ('计算机网络','计算机导论') and not exists(

Select * from sc where sno=student.sno and cno=course.cno)

));

18)查询选修了全部课程的学生的学号,姓名,系名。

select student.sno,sname,sdept from student where NOT exists     

(select  * from course where NOT exists    

(select * from sc where sc.sno = student.sno  and sc.cno = course.cno));

19)输出“高等数学”课程成绩前三名的学生的学号,姓名,系名

SELECT s.sno,sname,sdept from student s,sc,course c WHERE s.sno=sc.sno and sc.cno=c.cno AND cname='高等数学'

ORDER BY grade DESC LIMIT 3;
-- (不考虑成绩有重复值的情况)

数据库studymysql,完成下列查询

1)查询总经理、经理以下的职员信息,包括NULL值记录。

SELECT * FROM employee WHERE job_title is NULL

OR job_title not IN(

SELECT job_title from employee WHERE job_title='总经理'

OR job_title='经理'

);

2)查询“联荣资产”的客户信息

SELECT * from customer WHERE customer_name LIKE '%联荣资产%';

3)查询价格5000-6000的“联想”品牌和价格在5000以下的“小米”品牌的产品信息。

select * FROM product WHERE description LIKE '%联想%' AND price BETWEEN 5000 AND 6000 

UNION 

SELECT * FROM product WHERE description LIKE '%小米%' AND price < 5000;

4)查询如“GTX950M”/“GTX960M”系列的产品信息。

SELECT * FROM product WHERE description LIKE '%GTX950M%' OR description LIKE '%GTX960M%';

5)统计各年份订单总数,订单总额,按年份降序排列。

SELECT YEAR(pay_time),count(*) as number,sum(total_money) as money FROM payment GROUP BY YEAR(pay_time) ORDER BY YEAR(pay_time) DESC;

6)统计2016年各产品的订购数量(降序排列),输出5-10名的统计信息,包括产品ID,订购总数。

SET sql_mode=(SELECT REPLACE(@@sql_mode,'ONLY_FULL_GROUP_BY',''));

select product_id,payment.order_id, count(*), payment_id

from payment, order_detail where year(pay_time) = 2016 

and payment.order_id = order_detail.order_id group by order_id

order by buy_number desc limit 4,6;

总结

本篇设计大量的查询语句,初学者可能会对有些题产生困惑,这很正常,就好像人终究会被其年少不可得之物困扰一生,也会为一时一景解开其一生的困惑。加油吧少年!!

在这里插入图片描述

  • 41
    点赞
  • 63
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
create table sailors( sid char(10) primary key, sname char(20), rating int, age int); create table boats( bid char(10) primary key, bname char(20), color char(10)); create table reserves( sid char(10) , bid char(10) , rdate date, primary key(sid,bid,rdate), foreign key (sid) references sailors(sid) on delete cascade, foreign key (bid) references boats(bid) on delete cascade); insert into sailors(sid,sname,rating,age) values("22","dustin",7,45) ("29","brustus",1,33), ("31","lubber",8,56), ("32","andy",8,26), ("58","rusty",10,35), ("64","horatio",7,35), ("71","zorba",10,35), ("74","horatio",9,35), ("85","art",3,26), ("86","john",1,17), ("95","bob",3,64), ("96","frodo",3,26), ("98","tom",3,17); insert into boats(bid,bname,color) values("101","A","red"), ("102","B","green"), ("103","C","blue"), ("104","D","white") ("105","E","red"), ("106","F","blue"), ("107","G","green"); insert into reserves(sid,bid,rdata) values("22","101","2010-01-08"), ("22","102","2010-01-09"), ("29","103","2010-01-09"), ("31","102","2010-02-11"), ("22","104","2010-03-08"), ("22","103","2010-03-10"), ("32","105","2010-03-11"), ("32","106","2010-03-18"), ("32","102","2010-03-19"), ("58","104","2010-03-20"), ("64","105","2010-03-20"), ("95","101","2010-04-02"), ("85","102","2010-04-05"), ("22","101","2010-04-07"), ("22","105","2010-05-01"), ("22","106","2010-06-18"), ("22","107","2010-07-09"), ("31","106","2010-08-06"), ("32","105","2010-08-06"), ("29","104","2010-08-07"), ("64","103","2010-09-05"), ("58","102","2010-09-09"), ("64","104","2010-11-03"), ("64","105","2010-11-04"), ("31","106","2010-12-0
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

不会喷火的小火龙

你的鼓励是我最大的创作动力!

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值