4

史上最全SQL学习指南!(教程+实例+练习题)

 2 years ago
source link: https://zhuanlan.zhihu.com/p/381433715
Go to the source link to view the article. You can view the picture content, updated content and better typesetting reading experience. If the link is broken, please click the button below to view the snapshot at that time.

史上最全SQL学习指南!(教程+实例+练习题)

FLAG资深工程师,美帝代码搬运工,公众号:九章算法

报告称,未来10年数据细分岗位将扩张5倍,大数据19w的人才缺口将继续增加。国内外一线互联网公司纷纷开设了数据分析岗位。

v2-6720f52679f817e279326991a373ced9_720w.jpg

数据分析岗位中用的最频繁的工具就是SQL了。不论是满足业务日常取数需求,还是自己做分析,都离不开SQL。

最近,有不少想接触数据分析的同学,都在咨询系统学习SQL。如何学、怎么学、在哪学成了大家普遍的问题。

我们在领扣上新的SQL教程刚好能帮你解决这些问题!教程+实例+练习题,学过的人都反馈极高,最最重要是免费的!而且相信我,任何一个会基本数学运算的同学,从零开始搞定SQL只需五天。

那么,现在我们开始吧~ 学习SQL分成这样5个阶段

(ps:你也可以直接转战SQL教程~

阶段一:Hello SQL

  1. 简单的select语句

①使用 SELECT COLUMN 查询单个列

SELECT 语句是最常用的 SQL 语句,它能帮助我们从一个或多个表中查询信息。查询是数据库中最常用的功能,因此我们选择它作为 SQL 语句学习的第一步。

SELECT 语句用于从数据库中选取数据,并将结果存储在一个临时结果表中,这个表称为结果集。结果集实际上也是一种包含行与列的表,只不过是未持久化的,即临时表。

示例代码

在使用 SELECT 语句检索表数据时,至少需要给出两条信息——想检索的列名(column_name)和被检索内容的表名(table_name)。

基础语法如下:

大家可能会有些疑惑,列名 column_name 和表名 table_name 左右加的是什么?

这是反引号(``),它就在我们电脑键盘的左上角数字 1 的左边位置。

上述代码不加反引号的效果如下:

可能有些同学会问:在平时编写程序时不常加反引号,那不加反引号可以吗?反引号的作用是什么?

其实是可以的,在绝大部分时候,不加反引号并不会导致程序出错。但其实我们在命名字段的时候,字段名可能会与 SQL 关键字冲突,这时候要用反引号将列名和表名包含一下,避免关键字冲突。因此,在本课程所有小节的学习中,都会更加严谨地加上反引号。

当我们仅需要查询某一列的信息,且知道该列的列名时,可以使用简单的 SELECT COLUMN 的语句查询单个列来获取该列的信息。

我们可以通过下面的实例来感受一下 SELECT COLUMN 的用法。

假设我们要查询课程表 courses 中所有课程的名称。

我们可以使用下面的 SQL 语句:

执行输出结果

请通过下面 SELECT COLUMN 实例——查询所有课程名称,去实操一下吧!

查询所有课程名称

查询老师的姓名

使用 SELECT COLUMN, COLUMN 查询多个列

当我们想要从一个表中查询多个列时,使用的 SELECT 语句与查询一个列时使用的语句相似,但是需要在 SELECT 关键字后给出多个列名,并且列名之间必须以逗号分隔

语法:

我们可以通过下面的实例来感受一下 SELECT COLUMN, COLUMN 的用法。

假如我们要从课程表 courses 表中选取课程名称 name 和课程开课日期 created_at 的列。

我们可以使用下面的 SQL 语句:

执行输出结果

请通过下面SELECT COLUMN实例——查询课程名称和课程创建时间,去实操一下吧!

查询课程名称和课程创建时间

Check course name and class size

③使用 SELECT * 查询所有列

SELECT 语句可以直接检索表中所有信息,即检索所有的列。这可以通过在列名的位置使用星号( * )通配符来实现,输出的列的顺序一般是列在表定义中出现的物理顺序。

通配符是一类键盘字符,* (星号) 就是较为常用的通配符之一,可以使用 * 代替零个、单个或多个字符。 使用 * 通配符最大的优点就是,当不明确需要检索的列名时,可以通过检索所有列名来确定。

语法:

我们可以通过下面的实例来感受一下 SELECT * 的用法。

假如我们要查询课程表 courses 中的所有数据 。

我们可以使用下面的 SQL 语句:

  • * 表示所有列,是一种便捷式写法
  • FROM 关键字指出从哪个表中检索数据

执行输出结果:

请通过下面SELECT * 实例——查询所有课程,去实操一下吧!

查询所有课程

查询所有老师

使用 SELECT DISTINCT 查询不同行

经过上面的知识学习,我们可以发现 SELECT 语句会返回所有匹配的行,有时候会遇到数据相同的情况。如果我们只想知道有哪些不同的值,即希望查询的值都是唯一不重复的,我们该怎么办呢?这时候我们就需要用到 DISTINCT 关键字。

语法:

提示: DISTINCT 关键字需位于列名之前。

我们可以通过下面的实例来感受一下 SELECT DISTINCT 的用法。

假如我们想了解课程表 courses 中的授课教师有哪些,并查询教师的编号。

我们可以使用下面的 SQL 语句:

执行输出结果:

通过结果我们可以了解到,编号 4、编号 3 和编号 1 的三位教师会在本学期给学生上课。

请通过下面SELECT DISTINCT 实例——查询授课教师编号,去实操一下吧!

查询授课教师编号

Check the nationality of all teachers

使用 SELECT WHERE 对行进行筛选过滤

在大多数情况下,我们只希望留下感兴趣的行而过滤掉不感兴趣的行,这时我们可以使用 WHERE 子句来帮助我们。SELECT WHERE 语句是筛选查询很重要的操作,WHERE 关键字后面加上条件可以过滤掉我们不需要信息,对查询效率有着很大的提高。

在使用 SELECT WHERE 语句检索表数据时,需要给出检索的表名 (table_name)、检索的列名 (column_name) 和操作符 (operator) 。

语法:

  • column_name 对应指定列的名称,或者是多列,用逗号( , )分隔开
  • table_name 对应查询表的名称
  • operator 为操作符,常用的有等于 = 、小于 < 、大于 > 、不等于<>!=,我们会在后续课程中更加深入地学习它。

我们可以通过下面的实例来感受一下 SELECT WHERE 的用法。

如果我们想要查询我们可以选择哪些课,或者对一些感兴趣的课程想要详细了解,那我们要到课程信息中去一个一个查找吗?不!这里会给你最简单直接有效的方式:

如果我们要从课程表 courses 中选取课程名为 'System Design' 的课程。

我们可以使用下面的 SQL 语句:

执行输出结果:

请通过下面SELECT WHERE 实例——查询名称为 System Design 的课程信息,去实操一下吧!

Search for information on courses with more than 1000 participants

Find course information for the course named Artificial Intelligence

2.简单的insert语句

①使用 INSERT INTO 在不指定列的情况下插入数据

我们在学习了从表中查询数据后,如果希望在表中添加新的数据,那么该如何操作呢?这就需要用到我们的 INSERT INTO 语句了。

INSERT INTO 语句用于向表中插入新记录,这边介绍两种编写形式,第一种形式无需指定列名,第二种形式需要指定列名。

在本教程中,我们使用 Lintcode 样本数据库作为我们案例查询表。

在本章中,我们先讲讲 INSERT INTO 的第一种形式。这种形式,不需指定列名,只需提供要插入的数据即可,语法如下:

value1, value2 …… 为对应插入数据表中的值,每个值的属性需要与对应表中的列名属性相匹配,而且需要把插入的信息填写完整,否则会报错。

我们可以通过下面的实例来感受一下 INSERT INTO 第一种形式的用法。

假设我们要向课程表 courses 中插入一条新行。

我们可以使用下面的 SQL 语句:

执行输出结果

请通过下面INSERT INTO 实例(一)——向课程表中插入 Python 课程信息,去实操一下吧!

向课程表中插入 Python 课程信息

向课程表中插入 SQL 课程信息

②使用 INSERT INTO 在指定的列中插入数据

上一节,我们学习了INSERT INTO第一种形式的写法,接下来,我们来讲讲INSERT INTO的第二种形式。这种形式需要指定列名,语法如下:

其中 column1, column2 ... 为指定的列名,value1, value2 …… 为对应插入数据表中的值,每个值的属性需要与对应的列名属性相匹配。

由此我们不难发现,如果我们需要为表中的每一列插入数据,那么第一种形式的写法会更为方便,如果我们只想在指定列中插入数据,那么第二种形式的写法会更为方便。

我们可以通过下面的实例来感受一下 INSERT INTO 第二种形式的用法。

假如我们想向课程表 courses 插入一条新行,但是只在 namestudent_numbercreated_atteacher_id 列中插入数据( id 字段会自动更新):

我们可以使用下面的 SQL 语句:

INSERT INTO `courses` (`name`, `student_count`, `created_at`, `teacher_id`) VALUES ('Flash Sale','100','2018-01-01',5);

执行输出结果

mysql> INSERT INTO `courses` (`name`, `student_count`, `created_at`, `teacher_id`) VALUES ('Flash Sale','100','2018-01-01',5);
Query OK, 1 row affected (0.01 sec)

mysql> SELECT * FROM `courses`;
+----+-------------------------+---------------+------------+------------+
| id | name | student_count | created_at | teacher_id |
+----+-------------------------+---------------+------------+------------+
| 1 | Advanced Algorithms | 880 | 2020-06-01 | 4 |
| 2 | System Design | 1350 | 2020-07-18 | 3 |
| 3 | Django | 780 | 2020-02-29 | 3 |
| 4 | Web | 340 | 2020-04-22 | 4 |
| 5 | Big Data | 700 | 2020-09-11 | 1 |
| 6 | Artificial Intelligence | 1660 | 2018-05-13 | 3 |
| 7 | Java P6+ | 780 | 2019-01-19 | 3 |
| 8 | Data Analysis | 500 | 2019-07-12 | 1 |
| 10 | Object Oriented Design | 300 | 2020-08-08 | 4 |
| 12 | Dynamic Programming | 2000 | 2018-08-18 | 1 |
| 13 | Python | 400 | 2021-05-23 | 3 |
| 14 | Flash Sale | 100 | 2018-01-01 | 5 |
+----+-------------------------+---------------+------------+------------+
12 rows in set (0.00 sec)

请通过下面INSERT INTO 实例(二)——向课程表指定的列插入 'Flash Sale' 课程信息,去实操一下吧!

向课程表指定的列插入 'Flash Sale' 课程信息

Insert teacher information into the specified column of the teachers table

3.简单的update语句

使用 UPDATE 更新数据

在我们平时的使用中 UPDATE 语句,也是一种较常用的 SQL 语句,它可以用来更新表中已存在的记录。

我们在查询教师表 teachers 的时候发现,教师姓名 name 为 "Linghu Chong" 的老师邮箱 email 信息为 NULL,即没有该部分信息,我们现在希望更新邮箱信息,这时候就需要用到 UPDATE 语句。

语法

注意

请注意 UPDATE 语句中的 WHERE 子句!WHERE 子句规定哪条记录或者哪些记录需要更新。如果您省略了 WHERE 子句,所有的记录都将被更新!

我们可以通过下面的实例来感受一下 UPDATE 的用法。

假如我们想将教师名 name 为 "Linghu Chong" 的邮箱 email 更新为 '[email protected]'。

我们可以使用下面的 SQL 语句:

执行输出结果

我们查询"Linghu Chong" 老师的邮箱 email 后,可以发现邮箱已经更新为我们想要的 '[email protected]'。

请通过下面UPDATE 实例Ⅰ——更新指定教师的邮箱,去实操一下吧!

更新所有课程信息

Update on the number of students choosing artificial intelligence

4.使用 DELETE 删除数据

前面我们学习了插入,更新语句,但总有一些数据是我们不需要的,在实际生活中,会员卡过期,银行卡销户之类的,都需要用到 DELETE 关键字对原有的数据进行删除,下面我们就来介绍一下。

示例代码

  • table_name 代表表名称
  • some_column 代表列名称,如 id
  • some_value 可以为任意值。some_columnsome_value 构成 WHERE 子句中的搜索条件。

注意

请注意 SQL DELETE 语句中的 WHERE 子句。WHERE 子句规定哪条记录或者哪些记录需要删除。如果省略了 WHERE 子句,所有的记录都将被删除!

我们可以通过下面的实例来感受一下 DELETE 的用法。

假如我们要从课程表 courses 中删除课程名为 'Dynamic Programming' 的课程。

我们可以使用下面的 SQL 语句:

执行输出结果:

可以看出删除后的课程表 courses 已经查询不到课程名 name 为动态规划 'Dynamic Programming' 数据了。

注意

我们可以在不删除表的情况下,删除表中所有的行,这意味着表结构、属性、索引将保持不变。

在删除记录时要格外小心!因为不能重来!

请通过下面DELETE 实例——删除课程名为 Dynamic Programming 的课程,去实操一下吧!

Delete all courses until 2020

Delete all rows in the table

剩下的就不一一介绍了。可以移步SQL教程学习。

阶段二:运算符

1.比较运算符

Query the name of the Chinese teacher

Query teachers over 20 years old

2.逻辑运算符

Query the courses that meet the conditions taught by the specified teacher

Inquire about courses starting before May 2020

使用 NOT 过滤不满足条件的数据

使用 AND 连接多条件

Search for courses with an instructor id of less than 3 and more than 800 students

Query the course information of 'Web' or 'Big Data'

使用 OR 连接多个条件

3.特殊条件

Query courses with teacher id other than 1 and 3

Query teacher information by email

Inquire about Chinese and Japanese teachers who have e-mail addresses

Query course information for a specific time

使用 IS NULL 查询空数据

Query for course information about the number of students within the specified range

使用 NOT IN 排除

使用 BETWEEN AND 查询两值间的数据范围

使用 LIKE 模糊查询

使用 IN 查询多条件

4.ORDER BY 与 LIMIT

Check the age of teachers and sort them in ascending order

Sorted by age of Chinese teachers in descending order

使用 ORDER BY 对数据进行排序

Search for the oldest Chinese teacher

使用 LIMIT 限制输出行数

阶段三:函数

1.算数函数(一)

Check the age of the youngest teacher

Find the age of the oldest Chinese teacher

Count the total number of students for teacher #3

使用 MIN() 函数返回指定列中的最小值

使用 SUM() 函数统计数值列的总数

使用 AVG() 函数求数值列的平均值

2.算数函数(二)

Check the average age of teachers over 20 years old

Number of teachers aged 20 to 28 who are Chinese and British nationals

Check the information of teachers who do not have email and are older than 20 years old

使用 ROUND() 函数将数值四舍五入

使用 NULL() 函数判断空值

使用 COUNT() 函数计数

3.时间函数(一)

Search for course titles and course dates through August 2020

Query the hours of all course creation times

使用 NOW() 、 CURDATE()、CURTIME() 获取当前时间

The date the course was created is displayed in 'year-month-day hour:minute:second'

Insert the current date into the table

使用 EXTRACT() 函数提取指定的时间信息

使用 DATE()、TIME() 函数提取日期和时间

使用 DATE_FORMAT() 格式化输出日期

4.时间函数(二)

Calculate the number of months difference between the start date and the current date of all courses in the schedule

Postpone all course creation dates by one day

使用 DATE_SUB() 减少时间

使用 DATE_ADD() 增加时间

Calculate the number of days from 03/26/2019 to the course creation time

Advance all course creation dates by one day

使用时间函数 DATEDIFF() 和 TIMESTAMPDIFF() 计算日期差

阶段四:约束和多表连结

1.约束

检查约束 CHEC

主键约束 PRIMARY KEY

非空约束 NOT NULL

默认约束 DEFAULT

唯一约束 UNIQUE

外键约束 FOREIGN KEY

2.多表连结

联结

内连接 INNER JOIN

交叉连接 CROSS JOIN

外连接 OUTER JOIN

阶段五:查询

1.分组查询

HAVING 子句

GROUP BY 子句

2.简单的子查询

INSERT 语句中的子查询

UPDATE 语句中的子查询

SELECT 语句中的子查询

DELETE 语句中的子查询

3.子查询进阶

多列子查询

ALL 操作符的多行子查询

IN 操作符的多行子查询

内联视图子查询

HAVING 子句中的子查询

ANY 操作符的多行子查询

更多SQL学习路线,可参考LintCode官网的SQL教程


About Joyk


Aggregate valuable and interesting links.
Joyk means Joy of geeK