3、职能岗SQL学习极简攻略-水平学习SQL
水平学习SQL
在垂直学习中,我们学习了SQL的基础语法,包括SELECT、WHERE、GROUP BY、HAVING、ORDER BY、LIMIT等。接下来,我们将对每种SQL子句进行扩展,详细介绍每种子句的用法。
SELECT
SELECT部分是SQL中最重要的部分,用于查询数据。在垂直学习章节中,我们已经学习了SELECT的基础用法,包括查询所有列、查询部分列、基本的查询函数等。接下来将详细介绍SELECT的更多用法,大体分为函数、列的重命名两个方面。
函数
在SELECT部分,我们可以对返回的结果集进行处理。这样的处理操作我们称之为函数。
在SQL中有很多函数,用于对返回的结果集进行处理,例如MIN、MAX、DISTINCT、COUNT、SUM、AVG等。
以下我们将介绍这些函数的用法。
MIN
MIN函数用于计算返回的结果集中某一列的最小值。
例如我们想知道高能物理科目的最低分是多少,则可以使用以下语句:
1 | SELECT MIN(score) FROM scores_t WHERE subject = '高能物理'; |
将返回:
MIN(score) |
---|
29 |
MAX
MAX函数用于计算返回的结果集中某一列的最大值。
例如我们想知道创意写作科目的最高分是多少,则可以使用以下语句:
1 | SELECT MAX(score) FROM scores_t WHERE subject = '创意写作'; |
将返回:
MAX(score) |
---|
100 |
DISTINCT
当我们想对返回的结果去重时,可以使用DISTINCT来修饰列名。
例如我们只想知道有哪些同学,则可以使用以下语句:
1 | SELECT DISTINCT student_name FROM scores_t; |
将返回:
student_name |
---|
屈屈 |
慧心 |
达琳 |
COUNT
COUNT函数用于计算返回的结果集中有多少行数据。
例如当我们想知道有成绩表中一共有多少行记录,则可以使用以下语句:
1 | SELECT COUNT(*) FROM scores_t; |
将返回:
COUNT(*) |
---|
12 |
同时,COUNT也能与其它函数一起使用,例如我们想知道有多少个不同的学生,则可以使用以下语句:
1 | SELECT COUNT(DISTINCT student_name) FROM scores_t; |
将返回:
COUNT(DISTINCT student_name) |
---|
3 |
想知道不及格的成绩有多少个,则可以使用以下语句:
1 | SELECT COUNT(*) FROM scores_t WHERE score < 60; |
将返回:
COUNT(*) |
---|
2 |
SUM
SUM函数用于计算返回的结果集中某一列的和。
例如我们想知道成绩表中时尚美学科目的总分,则可以使用以下语句:
1 | SELECT SUM(score) FROM scores_t WHERE subject = '时尚美学'; |
AVG
AVG函数用于计算返回的结果集中某一列的平均值。
例如我们想知道成绩表中电子竞技科目的平均分,则可以使用以下语句:
1 | SELECT AVG(score) FROM scores_t WHERE subject = '电子竞技'; |
列的重命名
在SELECT部分,我们可以使用AS关键字对返回的结果集中的列进行重命名。
例如我们想知道成绩表中学生的姓名和分数,则可以使用以下语句:
1 | SELECT student_name AS 姓名, score AS 分数, subject AS 科目 FROM scores_t LIMIT 1; |
将返回:
姓名 | 分数 | 科目 |
---|---|---|
屈屈 | 100 | 创意写作 |
同时,我们也可以使用AS关键字对函数的返回值进行重命名。
例如我们想知道成绩表中电子竞技科目的平均分,则可以使用以下语句:
1 | SELECT AVG(score) AS 平均分 FROM scores_t WHERE subject = '电子竞技'; |
另外AS关键字可以省略,例如以下语句与上面的等价:
1 | SELECT AVG(score) 平均分 FROM scores_t WHERE subject = '电子竞技'; |
WHERE
筛选数据
WHERE用于筛选数据,在WHERE字句部分,我们常使用以下运算符对筛选条件进行修饰:
1 | = 、 > 、 < 、 >= 、 <= 、 != 、 |
其中:
- != 表示 不等于。
- BETWEEN 表示在某个范围内,例如 score BETWEEN 60 AND 80,表示成绩在60到80之间,等价于 score >= 60 AND score <= 80。
- IN 表示在某个集合内,例如 subject IN (‘电子竞技’, ‘创意写作’),表示科目是电子竞技或者创意写作。
- LIKE 表示模糊匹配,例如 student_name LIKE ‘屈%’,表示学生名字以屈开头的;百分号的位置可以在任意位置,例如 student_name LIKE ‘%琳’,则表示学生名字以琳结尾的;百分号可以有多个。
- IS NULL 表示为空,不常用。
- IS NOT NULL 表示不为空,不常用。
例如我们想知道成绩表中电子竞技科目的不及格的同学,则可以使用以下语句:
1 | SELECT * FROM scores_t |
将返回:
student_id | student_name | subject | score |
---|---|---|---|
3 | 达琳 | 电子竞技 | 59 |
条件组合
不同的WHERE条件可以通过AND和OR关键字组合使用。
例如我们想知道成绩表中电子竞技和高能物理科目不及格或优分(>=80分)的成绩,则可以使用以下语句:
1 | SELECT * FROM scores_t |
与以下SQL等价:
1 | SELECT * FROM scores_t |
PS:感受到不用BETWEEN的好处了吗,通过条件组合,我们可以更灵活地筛选数据。
拓展:AND优先级的优先级高于OR,例如A OR B AND C,等价于 A OR (B AND C)。
但是不用记,不要炫技,就记住使用括号来改变优先级即可。
GROUP BY
GROUP BY的作用是对数据进行分组,常与SELECT中的函数一起使用。除了在垂直学习章节中介绍的与SUM函数一起使用,还常与MIN、MAX、COUNT、AVG等函数一起使用。
例如我们想知道每个科目的平均分,则可以使用以下语句:
1 | SELECT subject, AVG(score) FROM scores_t |
将返回:
subject | AVG(score) |
---|---|
创意写作 | 91.3333 |
时尚美学 | 75.6667 |
电子竞技 | 80.6667 |
高能物理 | 63.6667 |
SELECT字句中也可以与多个函数一起使用。例如我们不仅想知道每个科目的平均分,还想知道最高分和最低分,则可以使用以下语句:
1 | SELECT subject, AVG(score), MIN(score), MAX(score) FROM scores_t |
将返回:
subject | AVG(score) | MIN(score) | MAX(score) |
---|---|---|---|
创意写作 | 91.3333 | 81 | 100 |
时尚美学 | 75.6667 | 62 | 100 |
电子竞技 | 80.6667 | 59 | 91 |
高能物理 | 63.6667 | 29 | 85 |
这样就能同时统计多个维度的数据了,一目了然。
除了对单个列进行分组,我们还可以对多个列进行分组。例如对于下面这张表,增加了班级列和部分同学的成绩。
student_id | student_name | class | subject | score |
---|---|---|---|---|
1 | 屈屈 | 1班 | 创意写作 | 100 |
1 | 屈屈 | 1班 | 时尚美学 | 100 |
1 | 屈屈 | 1班 | 电子竞技 | 92 |
1 | 屈屈 | 1班 | 高能物理 | 29 |
2 | 慧心 | 2班 | 创意写作 | 81 |
2 | 慧心 | 2班 | 时尚美学 | 62 |
2 | 慧心 | 2班 | 电子竞技 | 91 |
2 | 慧心 | 2班 | 高能物理 | 85 |
3 | 达琳 | 1班 | 创意写作 | 93 |
3 | 达琳 | 1班 | 时尚美学 | 65 |
3 | 达琳 | 1班 | 电子竞技 | 59 |
3 | 达琳 | 1班 | 高能物理 | 77 |
4 | 森贝 | 2班 | 创意写作 | 88 |
4 | 森贝 | 2班 | 时尚美学 | 75 |
4 | 森贝 | 2班 | 电子竞技 | 83 |
4 | 森贝 | 2班 | 高能物理 | 90 |
我们想按班级统计每个科目的平均分,则可以使用以下语句:
1 | SELECT class, subject, AVG(score) FROM scores_t |
将返回:
class | subject | AVG(score) |
---|---|---|
1班 | 创意写作 | 96.5000 |
1班 | 时尚美学 | 82.5000 |
1班 | 电子竞技 | 75.5000 |
1班 | 高能物理 | 53.0000 |
2班 | 创意写作 | 84.5000 |
2班 | 时尚美学 | 68.5000 |
2班 | 电子竞技 | 87.0000 |
2班 | 高能物理 | 87.5000 |
HAVING
HAVING的作用是对GROUP BY的结果进行筛选。例如我们想筛选平均分大于80的学生,则可以使用以下语句:
1 | SELECT student_name, AVG(score) FROM scores_t |
将返回:
student_name | AVG(score) |
---|---|
屈屈 | 80.2500 |
森贝 | 84.0000 |
注意这里前提是没有重名的学生,否则应该以学生ID作为分组依据。
如果我们想知道至少有一门科目成绩为满分的学生,则可以使用以下语句:
1 | SELECT student_name |
将返回:
student_name |
---|
屈屈 |
在HAVING字句中,我们还可以进行更复杂的判断,例如我们想知道至少有哪些同学有两门及以上科目成绩相同,则可以使用以下语句:
1 | SELECT student_name |
将返回:屈屈,因为屈屈同学的创意写作和时尚美学都考了100分。
ORDER BY
ORDER BY的作用是对返回的结果集进行排序。排序分为升序和降序两种情况:
- 升序,添加ASC关键字,默认情况下就是升序,所以也可以省略ASC关键字。
- 降序,添加DESC关键字
Tips:建议无论何时都不要省略关键字,因为这样可以让SQL语义更清晰,并且如果去记忆默认的排序方式,不累吗。
例如我们想升序查看电子竞技成绩表中的数据,则可以使用以下语句:
1 | SELECT * FROM scores_t |
student_id | student_name | class | subject | score |
---|---|---|---|---|
3 | 达琳 | 1班 | 电子竞技 | 59 |
4 | 森贝 | 2班 | 电子竞技 | 83 |
2 | 慧心 | 2班 | 电子竞技 | 91 |
1 | 屈屈 | 1班 | 电子竞技 | 92 |
ORDER BY也可以对多个列进行排序,例如我们想以降序方式查看所有成绩,但是又希望先查看1班的成绩,再查看2班的,即1班的成绩排在2班的前面。则可以使用以下语句:
1 | SELECT * FROM scores_t |
返回数据:
student_id | student_name | class | subject | score |
---|---|---|---|---|
1 | 屈屈 | 1班 | 创意写作 | 100 |
1 | 屈屈 | 1班 | 时尚美学 | 100 |
3 | 达琳 | 1班 | 创意写作 | 93 |
1 | 屈屈 | 1班 | 电子竞技 | 92 |
3 | 达琳 | 1班 | 高能物理 | 77 |
3 | 达琳 | 1班 | 时尚美学 | 65 |
3 | 达琳 | 1班 | 电子竞技 | 59 |
1 | 屈屈 | 1班 | 高能物理 | 29 |
2 | 慧心 | 2班 | 电子竞技 | 91 |
… | … | … | … | … |
LIMIT
LIMIT的作用是限制返回的结果集的行数。例如我们想知道成绩表中创意写作前三名的同学,则可以使用以下语句:
1 | SELECT * FROM scores_t |
student_id | student_name | class | subject | score |
---|---|---|---|---|
1 | 屈屈 | 1班 | 创意写作 | 100 |
3 | 达琳 | 1班 | 创意写作 | 93 |
4 | 森贝 | 2班 | 创意写作 | 88 |
LIMIT的另一个常见用法是分页,例如我们仅仅是想查看创意写作第3名的成绩,则可以使用以下语句:
1 | SELECT * FROM scores_t |
返回数据:
student_id | student_name | class | subject | score |
---|---|---|---|---|
4 | 森贝 | 2班 | 创意写作 | 88 |
其中OFFSET 2表示跳过前两行数据,即从第三行开始返回数据,LIMIT 1表示限制返回1行数据。
其中OFFSET关键词可以省略,例如以下语句与上面的等价:
1 | SELECT * FROM scores_t |
此时LIMIT后面的第一个数字表示跳过的行数,第二个数字表示限制返回的行数。
分页用法在实际工作中很常见,例如在网页中展示数据时,一页展示不下所有数据,就需要分页展示,这时候就可以使用LIMIT来实现。例如每页10条数据,要展示第5页的数据,就可以使用LIMIT 40, 10来实现。
拓展:在分页时,如果跳过的行数很多,会带来显著的性能问题,导致查询速度变慢。这种现象我们称之为深分页,因为数据库需要扫描和丢弃大量无用的数据行。