• 3 min read

SQL SELECT查询语句详解


在数据库操作中,数据查询是数据库的核心操作。只要你和数据库打交道,百分之八十的时间都在写查询语句。而在 SQL 语言中,提供数据查询功能的就是大名鼎鼎的 SELECT 语句。

SELECT 语句不仅使用方式灵活,而且功能极其丰富。今天,我们将通过一个具体的“学生-课程”数据库,手把手教你彻底掌握 SELECT 的各大核心子句!

1. 准备具体数据表

为了让大家能清晰地看到每条 SELECT 语句执行后的效果,我们先准备三张基础表:学生表(Student)、课程表(Course)和选课成绩表(Sc)。

表1:Student(学生表)

Sno (学号)Sname (姓名)Age (年龄)Dept (所在系)
03090101张功杰19信息系统
05090102吴肇星19计算机
05090106王娴18计算机

表2:Course(课程表)

Cno (课程号)Cname (课程名)Credit (学分)
140001数据库原理3
140501计算机网络3
110501会计学2

表3:Sc(选课成绩表)

Sno (学号)Cno (课程号)Grade (成绩)
0309010114000180
0309010114050185
0309010111050175
0509010214000190
0509010214050195

2. 基础查询:SELECT 与 FROM

SELECT 语句最基本的结构就是告诉数据库:“我要从哪张表(FROM),查哪些列(SELECT)”。

2.1 查询指定列与全部列

如果你只对部分属性列感兴趣,可以在 SELECT 后跟上具体的列名。

SELECT Sname, Age FROM Student;

如果想查询所有列,可以简单地使用 * 通配符代表全部列。

2.2 消除重复的行 (DISTINCT)

有时查询的结果中会有重复值(例如查询学校里都有哪些系)。如果使用了 DISTINCT 关键词,系统就会在结果中去掉重复的行。

SELECT DISTINCT Dept FROM Student;

结果集将只返回“信息系统”和“计算机”两行,如果没有 DISTINCT,缺省默认是保留重复行的(ALL)


3. 条件过滤:WHERE 子句

我们通常不需要表里的所有数据,此时可以通过 WHERE 子句来查询满足指定条件的元组。WHERE 支持丰富的查询条件:

  • 比较大小=, >, <, >=, <=, !=, <> 等。
  • 确定范围BETWEEN ... AND ...NOT BETWEEN
  • 确定集合INNOT IN,用来查找属性值属于指定集合的元组。
  • 字符匹配 (LIKE):这是非常强大的模糊查询工具。% 代表任意长度的字符串,_ 代表任意单个字符。如果遇到字符串本身包含 %_ 的情况,还需要使用 ESCAPE 短语来进行转义。
  • 空值查询:对于未录入或不知道的值,使用 IS NULLIS NOT NULL 来查询,注意不能使用 = 代替 IS
  • 多重条件:用逻辑运算符 ANDORNOT 将多个条件连接起来。

实战查询: 找出“计算机”系且年龄大于 18 岁的同学。

SELECT Sname, Age 
FROM Student 
WHERE Dept = '计算机' AND Age > 18;

(对照数据表,将精准返回“吴肇星, 19”这一条记录)


4. 数据统计:聚集函数 (Aggregate Functions)

为了增强检索功能,SQL 提供了许多方便的聚集函数:

  • COUNT(*):统计元组(行)的总个数。
  • SUM(<列名>) / AVG(<列名>):计算一列值的总和 / 平均值(仅限数值型)。
  • MAX(<列名>) / MIN(<列名>):求一列值中的最大值 / 最小值。

特别注意: 除了 COUNT(*) 之外,其他的聚集函数在计算时都会跳过空值(NULL)只处理非空值。而且,WHERE 子句中是不能使用聚集函数作为条件表达式的。


5. 分组与筛选:GROUP BY 与 HAVING

当我们想按某个维度进行统计(例如“求每个学生的平均成绩”)时,就需要用到 GROUP BYGROUP BY 子句将查询结果按某一列或多列的值分组,值相等的会被分入同一组。对查询结果分组的目的是为了细化聚集函数的作用对象;分组后,聚集函数将作用于每一个组,即每一组都有一个对应的函数计算值。

如果分组后还需要按一定条件对这些组进行筛选,就可以使用 HAVING 短语。

实战查询: 查询平均成绩大于 80 分的学生学号及其平均成绩。

SELECT Sno, AVG(Grade) AS 平均分
FROM Sc
GROUP BY Sno
HAVING AVG(Grade) > 80;

(结合聚集函数,系统会先按 Sno 将成绩表分为几组,然后分别计算每组的 AVG,最后利用 HAVING 剔除掉不满足 >80 条件的组)

区别提示: WHERE 作用于基本表或视图,从中选择满足条件的元组;而 HAVING 作用于组,用于从中选择满足条件的组。


6. 结果排序:ORDER BY 子句

最后,为了让展示的数据更有条理,我们可以使用 ORDER BY 子句对查询结果按照一个或多个属性列进行排序。

  • ASC(升序):从小到大排列(默认值)。
  • DESC(降序):从大到小排列。

实战查询: 查询选修了课程“140501”的学生学号和成绩,并按成绩从高到低排序。

SELECT Sno, Grade 
FROM Sc 
WHERE Cno = '140501' 
ORDER BY Grade DESC;

(根据 Sc 表,吴肇星(05090102)的 95 分会排在第一位,张功杰(03090101)的 85 分排在第二位)


总结

一个完整且复杂的单表 SELECT 查询通常遵循如下的标准语序骨架:

SELECT <目标列> 
FROM <表名> 
WHERE <行筛选条件> 
GROUP BY <分组依据列> 
HAVING <组筛选条件> 
ORDER BY <排序依据列> ASC|DESC;