SQL之单表查询

柔光的暖阳◎ 2023-07-22 07:59 185阅读 0赞

学习下面的内容之前请先执行这些代码,确保数据库和表存在 !

附上下面要用到的数据库和表的 SQL 语句,在数据库管理页面新建一个查询然后使用 CV 大法转移过去执行即可:

  1. -- 创建数据库 schoolTest
  2. create database schoolTest CHARACTER SET utf8 COLLATE utf8_general_ci;
  3. -- 使用数据库 schoolTest
  4. use schoolTest;
  5. -- 创建 Student 表(学生表)
  6. create table student
  7. (
  8. Sno varchar(9) primary key, -- 学号
  9. Sname varchar(20), -- 姓名
  10. Ssex varchar(2), -- 性别
  11. Sage smallint, -- 年龄
  12. Sdept varchar(20) -- 所在系
  13. );
  14. -- 创建 Course 表(课程表)
  15. create table Course
  16. (
  17. Cno varchar(4) primary key, -- 课程号
  18. Cname varchar(40), -- 课程名
  19. Cpno varchar(4), -- 先行课
  20. Ccredit smallint, -- 学分
  21. foreign key (Cpno) references Course (Cno) -- 外键关联到课程表的课程号,代表该课程之前必须上的课
  22. );
  23. -- 创建 SC 表(学生选课表)
  24. create table SC
  25. (
  26. Sno varchar(9), -- 学号
  27. Cno varchar(4), -- 课程号
  28. Grade smallint, -- 成绩
  29. primary key (Sno, Cno), -- 两个主键
  30. foreign key (Sno) references student (Sno), -- 外键关联到学生表的学号
  31. foreign key (Cno) references Course (Cno) -- 外检关联到课程表的课程号
  32. );
  33. -- 插入学生数据
  34. insert into student
  35. values ('201215121', '李勇', '男', '20', 'CS'),
  36. ('201215122', '刘晨', '女', '19', 'CS'),
  37. ('201215123', '王敏', '女', '18', 'MA'),
  38. ('201215125', '张立', '男', '19', 'IS');
  39. -- 因为有外键约束,所以必须按照顺序来
  40. insert into Course values ('2', '数学', null, 2);
  41. insert into Course values ('6', '数据处理', null, 2);
  42. insert into Course values ('4', '操作系统', '6', 3);
  43. insert into Course values ('7', 'PASCAL语言', '6', 4);
  44. insert into Course values ('5', '数据结构', '7', 4);
  45. insert into Course values ('1', '数据库', '5', 4);
  46. insert into Course values ('3', '信息系统', '1', 4);
  47. -- 学生选课数据
  48. insert into SC values ('201215121', '1', 92),
  49. ('201215121', '2', 85),
  50. ('201215121', '3', 88),
  51. ('201215122', '2', 90),
  52. ('201215122', '3', 80);

建完表之后是这样的:
20200329151435214.png
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzk0MTM2NA_size_16_color_FFFFFF_t_70
2020032915152070.png
下面请一定跟着我动手操作哦,这样印象才能更深刻!

我觉得学习 SQL 最重要的就是这一块内容,因为这是应用层,也就是说以后从事后端操作数据库就是用的这一内容,掌握了之后以后不管有什么业务需求你都可以搞定。

1、基本语法

  1. SELECT [ALL|DISTINCT] <目标列表达式>[,<目标列表达式>]
  2. FROM <表名或视图名>[,<表名或视图名> ]…|(SELECT 语句)
  3. [AS]<别名>
  4. [ WHERE <条件表达式> ]
  5. [ GROUP BY <列名1> [ HAVING <条件表达式> ] ]
  6. [ ORDER BY <列名2> [ ASC|DESC ] ];
  7. SELECT子句:指定要显示的属性列
  8. FROM子句:指定查询对象(基本表或视图)
  9. WHERE子句:指定查询条件
  10. GROUP BY子句:对查询结果按指定列的值分组,该属性列值相等的元组为一个组。通常会在每组中作用聚集函数。
  11. HAVING短语:只有满足指定条件的组才予以输出
  12. ORDER BY子句:对查询结果表按指定列值的升序或降序排序

2、单表查询

查询只涉及一个表的查询成为单表查询

2.1、选择表中的若干列

2.1.1、查询指定列:

查询全体学生的学号与姓名。

  1. SELECT Sno,Sname
  2. FROM Student;

20200329151238463.png
查询全体学生的姓名、学号、所在系。

  1. SELECT Sname,Sno,Sdept
  2. FROM Student;

20200329151259470.png

2.1.2、查询全部列:

查询全体学生的详细记录:

  1. SELECT Sno,Sname,Ssex,Sage,Sdept
  2. FROM Student;
  3. SELECT *
  4. FROM Student;

20200329151550467.png

注意这个 select * from ,相信我,这将会是你使用最频繁的 SQL 语句!

SELECT 子句的 <目标列表达式> 不仅可以为表中的属性列,也可以是表达式:

例如:查全体学生的姓名及其出生年份。

  1. SELECT Sname,2020-Sage /*假设现在为2020年*/
  2. FROM Student;

20200329151810676.png
查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名。

  1. SELECT Sname,'Year of Birth: ',2020-Sage,LOWER(Sdept)
  2. FROM Student;

20200329151852525.png
可以使用列别名改变查询结果的列标题,只需加个空格即可:

  1. SELECT Sname NAME,'Year of Birth:' BIRTH, 2014-Sage BIRTHDAY,LOWER(Sdept) DEPARTMENT
  2. FROM Student;

20200329152004411.png

2.2、 选择表中的若干元组

2.2.1、消除取值重复的行

如果没有指定 DISTINCT 关键词,则缺省为 ALL

栗子:查询选修了课程的学生学号。

  1. SELECT Sno FROM SC;
  2. 等价于:
  3. SELECT ALL Sno FROM SC;

输出结果为:
20200329152102144.png

指定 DISTINCT 关键词,去掉表中重复的行,DISTINCT 是不同的意思。

  1. SELECT DISTINCT Sno
  2. FROM SC;

执行结果为:
20200329152123326.png

2.2.2、查询满足条件的元组 ☆

这部分内容是重点中的重点,请大家一定重点掌握。

常用的查询条件如图:
watermark_type_ZmFuZ3poZW5naGVpdGk_shadow_10_text_aHR0cHM6Ly9ibG9nLmNzZG4ubmV0L3dlaXhpbl80Mzk0MTM2NA_size_16_color_FFFFFF_t_70 1

a、比较大小

查询计算机科学系全体学生的名单。

  1. SELECT Sname
  2. FROM Student
  3. WHERE Sdept='CS';

20200329152258353.png
查询所有年龄在20岁以下的学生姓名及其年龄。

  1. SELECT Sname,Sage
  2. FROM Student
  3. WHERE Sage < 20;

20200329152326209.png
查询考试成绩有不及格的学生的学号。

  1. SELECT DISTINCT Sno
  2. FROM SC
  3. WHERE Grade < 60;

该表中没有不及格的学生,故查询结果为空。

b、确定范围

这里使用谓词:

  1. BETWEEN AND NOT BETWEEN AND

栗子:
查询年龄在 20~23 岁(包括 20 岁和 23 岁)之间的学生的姓名、系别和年龄:

  1. SELECT Sname, Sdept, Sage
  2. FROM Student
  3. WHERE Sage BETWEEN 20 AND 23;

20200329152927857.png
查询年龄不在 20~23 岁之间的学生姓名、系别和年龄:

  1. SELECT Sname, Sdept, Sage
  2. FROM Student
  3. WHERE Sage NOT BETWEEN 20 AND 23;

20200329153000200.png

c、确定集合

使用谓词:`IN <值表>, NOT IN <值表>

栗子:

`查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。

  1. SELECT Sname, Ssex
  2. FROM Student
  3. WHERE Sdept in ('CS', 'MA', 'IS');

202003291533200.png
查询既不是计算机科学系、数学系,也不是信息系的学生的姓名和性别。

  1. SELECT Sname, Ssex
  2. FROM Student
  3. WHERE Sdept not in ('CS', 'MA', 'IS');

查询结果为空。

d、字符匹配

使用谓词:[NOT] LIKE ‘<匹配串>’ [ESCAPE ‘ <换码字符>’]

<匹配串> 可以是一个完整的字符串,也可以含有通配符%_

  1. % (百分号) 代表任意长度(长度可以为0)的字符串
  2. 例如 a%b 表示以 a 开头,以 b 结尾的任意长度的字符串
  3. _ (下横线) 代表任意单个字符。
  4. 例如 a_b 表示以 a 开头,以 b 结尾的长度为 3 的任意字符串

在编程语言中 % _ #,一般都为占位符,这里也可以理解为占位符

栗子:
查询学号为 201215121 的学生的详细情况。

  1. SELECT *
  2. FROM Student
  3. WHERE Sno LIKE '201215121';

20200329153507809.png
等价于:

  1. SELECT *
  2. FROM Student
  3. WHERE Sno = '201215121';

查询所有姓刘学生的姓名、学号和性别。

  1. SELECT Sname, Sno, Ssex
  2. FROM Student
  3. WHERE Sname LIKE '刘%';

20200329153614111.png
查询姓”欧阳”且全名为三个汉字的学生的姓名。

  1. SELECT Sname
  2. FROM Student
  3. WHERE Sname LIKE '欧阳__';

查询结果为空。

查询名字中第2个字为”阳”字的学生的姓名和学号。

  1. SELECT Sname,Sno
  2. FROM Student
  3. WHERE Sname LIKE '__阳%';

查询结果为空。

查询所有不姓刘的学生姓名、学号和性别。

  1. SELECT Sname, Sno, Ssex
  2. FROM Student
  3. WHERE Sname NOT LIKE '刘%';

20200329153801794.png
但是设想一种情况就是,如果你要查询的属性名就带有_这个字符该怎么办 ? 因为他默认会被看作是占位符。

解决方案就是使用转义字符,是的,这一点和其他编程语言一样,就是用 \

栗子:
查询以”DB_“开头,且倒数第 3 个字符为 i 的课程的详细情况。

  1. SELECT *
  2. FROM Course
  3. WHERE Cname LIKE 'DB\_%i_ _' ESCAPE '\ ' ;

ESCAPE ‘’ 表示“ ” 为换码字符

e、涉及空值的查询

在实际的开发环境中,有时候会有很多数据查出来是空的,这对我们来说是没有用处的数据,我们可以使用 SQL 语句过滤掉这些数据。

使用谓词IS NULL 或 IS NOT NULL

“IS” 不能用 “=” 代替

栗子:
某些学生选修课程后没有参加考试,所以有选课记录,但没有考试成绩。查询缺少成绩的学生的学号和相应的课程号。

  1. SELECT Sno, Cno
  2. FROM SC
  3. WHERE Grade IS NULL;

查询结果为空。

查所有有成绩的学生学号和课程号。

  1. SELECT Sno, Cno
  2. FROM SC
  3. WHERE Grade IS NOT NULL;

20200329154045879.png

f、多重条件查询

使用逻辑运算符:AND和 OR

AND 的优先级高于 OR
可以用括号改变优先级

栗子:
查询计算机系年龄在 20 岁以下的学生姓名。

  1. SELECT Sname
  2. FROM Student
  3. WHERE Sdept = 'CS'
  4. AND Sage < 20;

20200329154126203.png
查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别。

还记得这个例子吗? 这是使用谓词 IN 确定集合的例子,当时我们是这样实现的:

  1. SELECT Sname, Ssex
  2. FROM Student
  3. WHERE Sdept IN ('CS ','MA ','IS');

现在他也可以这样实现:

  1. SELECT Sname, Ssex
  2. FROM Student
  3. WHERE Sdept = 'CS'
  4. OR Sdept = 'MA'
  5. OR Sdept = 'IS';

20200329154218900.png

2.3、 ORDER BY子句

ORDER BY 子句的作用就是字面意思 排序 :

可以按一个或多个属性列排序
升序:ASC;降序:DESC;缺省值为升序

栗子:
查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列。

  1. SELECT Sno, Grade
  2. FROM SC
  3. WHERE Cno= ' 3 '
  4. ORDER BY Grade DESC;

20200329154319756.png
查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列。

  1. SELECT *
  2. FROM Student
  3. ORDER BY Sdept, Sage DESC;

20200329154348697.png

2.4、 聚集函数

聚集函数是啥子? 有什么用?其实他就是个函数,方便我们运算。

  1. 统计元组个数
  2. COUNT(*)
  3. 统计一列中值的个数
  4. COUNT([DISTINCT|ALL] <列名>)
  5. 计算一列值的总和(此列必须为数值型)
  6. SUM([DISTINCT|ALL] <列名>)
  7. 计算一列值的平均值(此列必须为数值型)
  8. AVG([DISTINCT|ALL] <列名>)
  9. 求一列中的最大值和最小值
  10. MAX([DISTINCT|ALL] <列名>)
  11. MIN([DISTINCT|ALL] <列名>)

栗子:
查询学生总人数。

  1. SELECT COUNT(*)
  2. FROM Student;

20200329154453738.png
查询选修了课程的学生人数。

  1. SELECT COUNT(DISTINCT Sno)
  2. FROM SC;

20200329154515987.png
计算 1 号课程的学生平均成绩。

  1. SELECT AVG(Grade)
  2. FROM SC
  3. WHERE Cno='1';

20200329154541520.png
查询选修 1 号课程的学生最高分数。

  1. SELECT MAX(Grade)
  2. FROM SC
  3. WHERE Cno='1';

20200329154606996.png
查询学生 201215121 选修课程的总学分数。

  1. SELECT SUM(Ccredit)
  2. FROM SC,
  3. Course
  4. WHERE Sno = '201215121'
  5. AND SC.Cno = Course.Cno;

20200329154708178.png

2.5、 GROUP BY子句

它的作用是细化聚集函数的作用对象:

  • 如果未对查询结果分组,聚集函数将作用于整个查询结果
  • 对查询结果分组后,聚集函数将分别作用于每个组
  • 按指定的一列或多列值分组,值相等的为一组

栗子:

求各个课程号及相应的选课人数。

  1. SELECT Cno,COUNT(Sno)
  2. FROM SC
  3. GROUP BY Cno;

查询结果为:
20200329154848524.png
查询选修了 2 门以上课程的学生学号。

  1. SELECT Sno
  2. FROM SC
  3. GROUP BY Sno
  4. HAVING COUNT(*) > 2;

20200329154940133.png
查询平均成绩大于等于 80 分的学生学号和平均成绩:

下面的语句是不对的

  1. SELECT Sno, AVG(Grade)
  2. FROM SC
  3. WHERE AVG(Grade)>=80
  4. GROUP BY Sno;

因为 WHERE子句中是不能用聚集函数作为条件表达式

  1. SELECT Sno, AVG(Grade)
  2. FROM SC
  3. GROUP BY Sno
  4. HAVING AVG(Grade) >= 80;

20200329155225478.png
下面我们来看一下HAVING短语与WHERE子句的区别:

  • 作用对象不同
  • WHERE 子句作用于基表或视图,从中选择满足条件的元组
  • HAVING 短语作用于组,从中选择满足条件的组。

    以上所有操作的源码如下:

    — 查询全体学生的学号与姓名
    SELECT Sno, Sname
    FROM Student;

    — 查询全体学生的姓名、学号、所在系
    SELECT Sname, Sno, Sdept
    FROM Student;

    — 查询全体学生的详细记录
    SELECT *
    FROM Student;

    — 查全体学生的姓名及其出生年份
    SELECT Sname, 2020 - Sage /假设现在为2020年/
    FROM Student;

    — 查询全体学生的姓名、出生年份和所在的院系,要求用小写字母表示系名
    SELECT Sname, ‘Year of Birth: ‘, 2020 - Sage, LOWER(Sdept)
    FROM Student;

    — 可以使用列别名改变查询结果的列标题,只需加个空格即可
    SELECT Sname NAME, ‘Year of Birth:’ BIRTH, 2014 - Sage BIRTHDAY, LOWER(Sdept) DEPARTMENT
    FROM Student;

    — 查询选修了课程的学生学号
    SELECT Sno
    FROM SC;

    — 指定 DISTINCT 关键词,去掉表中重复的行
    SELECT DISTINCT Sno
    FROM SC;

    — 查询计算机科学系全体学生的名单
    SELECT Sname
    FROM Student
    WHERE Sdept = ‘CS’;

    — 查询所有年龄在20岁以下的学生姓名及其年龄
    SELECT Sname, Sage
    FROM Student
    WHERE Sage < 20;

    — 查询考试成绩有不及格的学生的学号
    SELECT DISTINCT Sno
    FROM SC
    WHERE Grade < 60;

    — 查询年龄在 20~23 岁(包括 20 岁和 23 岁)之间的学生的姓名、系别和年龄
    SELECT Sname, Sdept, Sage
    FROM Student
    WHERE Sage BETWEEN 20 AND 23;

    — 查询年龄不在 20~23 岁之间的学生姓名、系别和年龄
    SELECT Sname, Sdept, Sage
    FROM Student
    WHERE Sage NOT BETWEEN 20 AND 23;

    — 查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别
    SELECT Sname, Ssex
    FROM Student
    WHERE Sdept in (‘CS’, ‘MA’, ‘IS’);

    — 查询既不是计算机科学系、数学系,也不是信息系的学生的姓名和性别
    SELECT Sname, Ssex
    FROM Student
    WHERE Sdept not in (‘CS’, ‘MA’, ‘IS’);

    — 查询学号为 201215121 的学生的详细情况
    SELECT
    FROM Student
    WHERE Sno LIKE ‘201215121’;
    — 等价于
    SELECT

    FROM Student
    WHERE Sno = ‘201215121’;

    — 查询所有姓刘学生的姓名、学号和性别
    SELECT Sname, Sno, Ssex
    FROM Student
    WHERE Sname LIKE ‘刘%’;

    — 查询姓”欧阳”且全名为三个汉字的学生的姓名
    SELECT Sname
    FROM Student
    WHERE Sname LIKE ‘欧阳__’;

    — 查询名字中第2个字为”阳”字的学生的姓名和学号
    SELECT Sname, Sno
    FROM Student
    WHERE Sname LIKE ‘__阳%’;

    — 查询所有不姓刘的学生姓名、学号和性别
    SELECT Sname, Sno, Ssex
    FROM Student
    WHERE Sname NOT LIKE ‘刘%’;

    — 某些学生选修课程后没有参加考试,所以有选课记录,但没 有考试成绩。查询缺少成绩的学生的学号和相应的课程号
    SELECT Sno, Cno
    FROM SC
    WHERE Grade IS NULL;

    — 查所有有成绩的学生学号和课程号
    SELECT Sno, Cno
    FROM SC
    WHERE Grade IS NOT NULL;

    — 查询计算机系年龄在 20 岁以下的学生姓名。
    SELECT Sname
    FROM Student
    WHERE Sdept = ‘CS’
    AND Sage < 20;

    — 查询计算机科学系(CS)、数学系(MA)和信息系(IS)学生的姓名和性别
    SELECT Sname, Ssex
    FROM Student
    WHERE Sdept = ‘CS’
    OR Sdept = ‘MA’
    OR Sdept = ‘IS’;

    — 查询选修了3号课程的学生的学号及其成绩,查询结果按分数降序排列
    SELECT Sno, Grade
    FROM SC
    WHERE Cno = ‘3’
    ORDER BY Grade DESC;

    — 查询全体学生情况,查询结果按所在系的系号升序排列,同一系中的学生按年龄降序排列
    SELECT *
    FROM Student
    ORDER BY Sdept, Sage DESC;

    — 查询学生总人数
    SELECT COUNT(*)
    FROM Student;

    — 查询选修了课程的学生人数
    SELECT COUNT(DISTINCT Sno)
    FROM SC;

    — 计算 1 号课程的学生平均成绩
    SELECT AVG(Grade)
    FROM SC
    WHERE Cno = ‘1’;

    — 查询选修 1 号课程的学生最高分数
    SELECT MAX(Grade)
    FROM SC
    WHERE Cno = ‘1’;

    — 查询学生 201215121 选修课程的总学分数
    SELECT SUM(Ccredit)
    FROM SC,

    1. Course

    WHERE Sno = ‘201215121’
    AND SC.Cno = Course.Cno;

    — 求各个课程号及相应的选课人数
    SELECT Cno, COUNT(Sno)
    FROM SC
    GROUP BY Cno;

    — 查询选修了 2 门以上课程的学生学号
    SELECT Sno
    FROM SC
    GROUP BY Sno
    HAVING COUNT(*) > 2;

    — 查询平均成绩大于等于 80 分的学生学号和平均成绩
    SELECT Sno, AVG(Grade)
    FROM SC
    GROUP BY Sno
    HAVING AVG(Grade) >= 80;

发表评论

表情:
评论列表 (有 0 条评论,185人围观)

还没有评论,来说两句吧...

相关阅读

    相关 SQL查询

    学习下面的内容之前请先执行这些代码,确保数据库和表存在 ! 附上下面要用到的数据库和表的 SQL 语句,在数据库管理页面新建一个查询然后使用 CV 大法转移过去执行即可: