SQL(Structured Query Language)
1. SQL 操作
SQL, Structured Query Language, 结构化查询语言,用来查询关系数据库中的数据。
SELECT * FROM celebs;
关系型数据库由许多表组成,一张表由行和列组成。
一列通过表示数据的某个属性。
一个单独的行表示一组信息的观察值。
例如有如下表celebs
id | name | age |
1 | 张三 | 30 |
2 | 李四 | 25 |
3 | 王五 | 32 |
存储在数据库中的信息是有类型的:
- 整形(INTEGER)
- 文本(TEXT)
- 日期(DATA), 格式为YYYY-MM-DD
- REAL(实数), 存储小数类型
SQL 语句是数据库可以识别的语句,是人与数据数据进行交互的语言,末尾以分号结束。
例如,如下格式
CREATE TABLE table_name ( column_1 data_type, column_2 data_type, column_3 data_type );
CREATE TABLE 是一个命令,表示执行特定的数据操作,为了便于识别,命令一般大写。
table_name 表示创建的表的名称。
排号中的语句是参数信息,使用逗号分开
1.1 CREATE 命令
CREATE 命令可以让数据库创建新的表。例如,如下语句
CREATE TABLE celebs ( id INTEGER, name TEXT, age INTEGER );
1.2 INSERT 插入
INSERT 命令可以在表中插入一行数据
INSERT INTO celebs (id, name, age) VALUES (1, '张三', 22);
INSERT INTO 是命令,在表中插入一行值
celebs 是表名
(id, name, age) 是插入表中的属性
VALUES 是插入表中的属性值
1.3 SELECT 选择
SELECT 语言是从数据库中选择数据。
以下命令返回celebs表中name列中所有数据
SELECT name FROM celebs;
- SELECT 是关键字
- name 表示列,即数据的属性值
- FROM 是关键字
- celebs 是表名
也可以使用以下命令查询表中所有数据
SELECT * FROM celebs;
* 表示通配符,即表示表中所有的列。
1.4 ALTER 修改表
ALTER TABLE 命令可以增加一列至当前表中。
以下命令增加一列tel在celebs表中
ALTER TABLE celebs ADD COLUMN tel TEXT;
如果在插入时,示指定值,则默认是NULL。
1.5 UPDATE 更新
UPDATE 可以更新表格中的某行数据。
以下语句更新celebs 表中 tel 中的值为 13688888888
UPDATE celebs SET tel = "13688888888" WHERE id = 3
1.6 DELETE 删除
DELETE 可以删除表表格中的一行或多行数据。
DELETE FROM celebs WHERE tel IS NULL;
1.7 Constraints 限定
Constraints可以为列限制约束条件,可以优化表格中的数据,使数据看起来整齐。
CREATE TABLE celebs ( id INTEGER PRIMARY KEY, name TEXT UNIQUE, date_of_birth TEXT NOT NULL, date_of_death TEXT DEFAULT 'Not Applicable' );
PRIMARY KEY (主键) 列表示可以唯一标识一行数据,如果插入相同id数据,则会报错。
UNIQUE(唯一)表示该列数据在数据表中唯一
NOT NULL 表示该列必须有数据
DEFAULT 表示如果没有值,则使用该默认值。
2. 查询
当一张数据库表很大时,我们可以使用不同的查询命令获得不同的结果。来了解我们的数据。
2.1 查询所有数据
SELECT * FROM movies;
2.2 查询单独某列的数据
SELECT column1, column2 FROM table_name;
为了便于阅读,将FROM入到下一行中。
2.3 AS 关键词
假设有如下SQL语句
SELECT name AS 'Titles' FROM movies;
AS 的作用是将搜索出来的结果集的列名使用Titles替换掉。
有两点要说明:
第一,AS后面的名称最好使用单引号引起来,以提示注意
第二,AS只作用于搜索出来的结果,不会对原始表格列名作修改。
2.4 Distinct 关键词
当我们要检查一个表中的数据时,有时只想知道表格中有什么数据,不想要看重复的数据。
例如如下SQL 查询命令
SELECT age FROM user;
返回结果:
22
25
27
30
27
25
如果想要去除重复的数据,可以使用如下命令
SELECT DISTINCT age FROM user;
返回结果
22
25
27
30
2.5 Where 关键词
假设从用户表中,我只想要知道年龄大于25的人
SELECT * FROM users WHERE age > 25;
以上的命令搜索结果输出所有年龄大于25的人。
在上面的 where 后面是一个表达式语句,WHERE 只返回是TRUE的真。
SQL 中有如下查询条件
=
等于!=
不等于>
大于<
小于>=
大于或等于<=
小于或等于
2.6 LIKE 关键词
LIKE 也是一个操作运算符,当你想要查看相似的结果时,可以使用该关键词
假设用户的姓名是中有王阿美,我想知道表中有多少姓王且以美结尾的用户
SELECT * FROM users WHERE name LIKE '王_美';
本例中使用下划线来匹配以王开头且以美结尾的用户名
如果我只想知道以姓王的开头,则可以使用 %
SELECT * FROM users WHERE name LIKE '王%';
注意
‘王%’ 表示是以王开头的用户名
‘%王’ 表示是以王结尾的用户名
%阿% 表示用户名中只要有阿字的都会被匹配出来
% 对大小写不敏感,如果是英文字符,Zhang 与 zhang 都会被匹配住。
2.7 IS NULL
在数据表中, 有时,一些值是NULL。
我们可以使用如下操作符去判断是否为NULL
IS NULL
IS NOT NULL
比如查看用户表中age参数不为空的数据
SELECT name FROM users WHERE age IS NOT NULL;
2.8 BETWEEN
Between 也是一个操作符,用来获取一段日期、数据或者文本。
比如想查询用户表中年龄在20到29之间的人
SELECT * FROM users WHERE age BETWEEN 20 AND 29;
当使用英文查询时,过滤顺序则以字母形式,比如获取A 到 J 中的字母
SELECT * FROM movies WHERE name BETWEEN 'A' AND 'J';
2.9 AND 关键词
有时,查询的语句不止一条,可以使用AND进行连接
SELECT * FROM movies WHERE year BETWEEN 1990 AND 1999 AND genre = 'romance';
第一条 , 是 年份在 1990 到 1999 年之间
第二条, 是genre 表示该值为 romance
AND 表示且的关系。
2.10 OR 关键词
与AND使用方法相同,但是OR表示或的关系 。
2.11 ORDER BY 关键词
ORDER BY 表示对输出的结果进行排列。 有升序 与 逆序的区别,默认是升序,如果使用DESC则表示降序。
SELECT * FROM users ORDER BY age;
以上是对年龄进行升序排列。
降序的写法如下
SELECT * FROM movies WHERE imdb_rating > 8 ORDER BY year DESC;
如果是写成升序的,则ASC
SELECT * FROM users ORDER BY age ASC;
2.12 LIMIT 关键词
如果获取列表中的数据太多,则可以使用LIMIT 关键字进行限制。
SELECT * FROM users LIMIT 10;
以上命令是仅获取10行数据。
2.13 CASE 关键词
CASE 类似于 switch-case 语句的功能
SELECT name, CASE WHEN age < 14 THEN 'young' WHEN age < 40 THEN 'adult' ELSE 'old' END FROM users;
上述语句有几个注意点:
如果 WHEN 后面的语句是TRUE, 则使用THEN
CASE 与 END 是一对
3. 聚合函数
SQL 语句不仅可以用来在数据库查询数据,也可以用来做些计算。
对于表格中不同的行进行计算,叫做聚合(aggregates)。
以下是聚合的操作的关键命令
COUNT()
: 统计计算出来的有多少行SUM()
: 对列中所有数据进行求和MAX()
/MIN()
: 最大值与最小值AVG()
: 列中的均值ROUND()
: 近似值
3.1 COUNT 函数
如果想要知道结果数据集中有多少行, 则可以使用COUNT()函数
用法如下
SELECT COUNT(*) FROM table_name;
表示统计所有行数。
假设要统计价格为零的总数
SELECT COUNT(*) FROM fake_apps WHERE price = 0;
3.2 SUM() 函数
想要获取下载次数的总数
SELECT SUM(downloads) FROM fake_apps;
3.3 MAX()/MIN() 函数
MAX 与 MIN 返回一列中最大值与最小值。
SELECT MAX(downloads) FROM fake_apps;
获取app下载次数最大值。
3.4 AVERAGE 均值
SQL 使用AVG()函数快速获取一列的均值。
SELECT AVG(downloads) FROM fake_apps;
3.5 ROUND() 函数
假设数据中的数字有小数值,3.45, 2.67 则可以使用ROUND,只取一位小数
SELECT ROUND(price, 0) FROM fake_apps;
返回值如下
ROUND(price, 0) |
---|
0.0 |
1.0 |
0.0 |
2.0 |
15.0 |
0.0 |
3.0 |
4.0 |
15.0 |
SELECT ROUND(AVG(price), 2) FROM fake_apps;
还可以嵌入式的用。
3.6 GROUP BY 关键字
假设我们要知道每年电影评论的均值
SELECT AVG(imdb_rating) FROM movies WHERE year = 1999; SELECT AVG(imdb_rating) FROM movies WHERE year = 2000; SELECT AVG(imdb_rating) FROM movies WHERE year = 2001;
我们可以通过GROUP BY 有更好的写法
SELECT year, AVG(imdb_rating) FROM movies GROUP BY year ORDER BY year;
有时,我们想要根据分类信息获取总数数据。
SELECT ROUND(imdb_rating), COUNT(name) FROM movies GROUP BY ROUND(imdb_rating) ORDER BY ROUND(imdb_rating);
以上表示获取 1, 2, 3, 4, 5 每个评分分类阶段的总数。
还可以使用数字对每列数据进行查询
1
表示第一列2
表示第二列3
表示第三列
SELECT ROUND(imdb_rating), COUNT(name) FROM movies GROUP BY 1 ORDER BY 1;
3.7 HAVING 关键词
除了使用GROUP BY 对数据进行分类查看,SQL 还可以让包括或者不包括某些信息
SELECT year, genre, COUNT(name) FROM movies GROUP BY 1, 2 HAVING COUNT(name) > 10;
HAVING 与 WHERE 很像,而且可以使用HAVING替代。但一般遵守如下规定:
当我们对表中的数据量进行过滤时,使用WHERE
当我们想要对表中的分类数据进行过滤时,使用HAVING
4. 多表查询
为了更加有效的存储数据,我们经常将数据存储在不同的表中。
例如,我们有一家杂志公司,用户可以订阅不同的杂志。不同的订阅类型拥有不同的属性与权限。
每个用户又拥有多种关联数据。
我们可以用一个表创建如下信息
order_id
customer_id
customer_name
customer_address
subscription_id
subscription_description
subscription_monthly_price
subscription_length
purchase_date
但是,上面有许多重复的信息。如果一个用户拥有多个订阅。用户名称与地址将会重复许多遍。
如果相同的订阅类型由许多客户订阅,则订阅价格与订阅描述信息就会重复放多遍。
所以可以将数据分别放在如下三个表中
订单表orders,仅包含订单相关信息:
- order_id
- customer_id
subscription_id
purchase_date
订阅表subscriptions, 可以包含描述每个订阅类的信息
subscription_id
- description
- price_per_month
- subscription_length
用户表 customers, 可以包含订阅的客户信息
- customer_id
- customer_name
- address
4.1 JOIN 关键词
JOIN 可以联合多个表中的数据,用法如下:
SELECT * FROM orders JOIN customers ON orders.customer_id = customers.customer_id;
上述表示在orders 与 customers 表中查找所有客户id相同的列
可以与WHERE联用
SELECT * FROM orders JOIN subscriptions ON orders.subscription_id = subscriptions.subscription_id WHERE subscriptions.description = 'Fashion Magazine';
4.1.1 INNER JOIN
默认情况下,JOIN 是内联的即有如下数据
表1
C1 | C2 |
A | B |
Q | W |
X | Y |
表2
C2 | C3 |
B | C |
E | R |
Y | Z |
则使用JOIN联接C2, 则会是以下结果集
C1 | C2 | C3 |
A | B | C |
X | Y | Z |
4.1.2 LEFT JOIN
如果我们想要在JOIN的时候,保留左侧的数据,则可以使用LEFT JOIN
表1, 表2 数据集还是如上,如果使用LEFT JOIN 则会有如下结果集
SQL 代码如下
SELECT * FROM table1 LEFT JOIN table2 ON table1.c2 = table2.c2;
结果如下
C1 | C2 | C3 |
A | B | C |
Q | W | |
X | Y | Z |
该结果集会丢弃表2中不相等的数据
4.2 主键与外键
主键表示可以唯一标识表中一行数据的值,例如上面三个表中的order_id, subscription_id, customer_id
主键有如下要求:
所有值必须为非NULL
- 所有值必须是唯一的.
- 一张表中只有一个列是主键
外键表示当一张表中的主键列出现在另一张表中的时候,则叫外键。
在使用多表进行查询时,经常会使用外键来匹配。
例如某学校有两张表,classes 与 students
- 课程表包含所有课程信息,主键
id
. - 学生表包含所有的学生信息,主键是ID. 他还拥有一个class_id,是外键,与课程表中的id对应
使用INNER JOIN 将上面两个表联接起来
SELECT * FROM classes JOIN students ON classes.id = students.class_id;
4.3 CROSS JOIN
有时我们想要知道一个表中一列数据与另一个表中所有数据的组合,就可以使用CROSS JOIN
SELECT shirts.shirt_color, pants.pants_color FROM shirts CROSS JOIN pants;
假设shirt_color列中有3个数据,pants_color 中有2个数据,则共有 2* 3 个数据。
4.4 UNION 关键字
假设表1 有如下
pokemon | type |
a | 1 |
b | 2 |
c | 3 |
表2 有如下数据
pokemon | type |
f | 5 |
则使用如下命令可以联合
SELECT * FROM table1 UNION SELECT * FROM table2;
结果为
pokemon | type |
a | 1 |
b | 2 |
c | 3 |
f | 5 |
这个使用情况必须列数相同
4.5 WITH 关键词
假设市场部门想要知道每个用户订购了多少个杂志产品。
我们首先可以使用如下SQL语句
SELECT customer_id, COUNT(subscription_id) AS 'subscriptions' FROM orders GROUP BY customer_id;
这个查询可以查出所有订阅的用户id, 但是无法给出所有用户名称。
我们可以使用如下格式的结果
WITH previous_results AS ( SELECT ... ... ... ... ) SELECT * FROM previous_results JOIN customers ON _____ = _____;
使用上面的格式
WITH previous_query AS ( SELECT customer_id, COUNT(subscription_id) AS 'subscriptions' FROM orders GROUP BY customer_id ) SELECT customers.customer_name, previous_query.subscriptions FROM previous_query JOIN customers ON previous_query.customer_id = customers.customer_id;