TIP
SQL
不区分大小写(除了表格名)。
但书写 SQL
关键字时,我们推荐用大写形式。
这有助于我们把关键字和 表名、列名区分开,让 SQL
更容易理解。
查询所有列
SELECT *
FROM tableName
查询指定列
SELECT column, another_column, …
FROM tableName
基础条件查询
SELECT column, another_column, …
FROM tableName
WHERE condition
AND/OR another_condition
AND/OR …
条件 condition
是包含操作符 operator
的表达式。
以下操作符可以用来筛选数字属性列:
Operator | Condition | Example |
---|---|---|
= != < <= > >= | 比较运算 | goods_num > 100 |
BETWEEN...AND... | 在区域之间 | goods_num BETWEEN 100 AND 1000 |
NOT BETWEEN...AND... | 不在区域之间 | goods_num NOT BETWEEN 100 AND 1000 |
IN (...) | 在列表中 | goods_num IN (200, 400, 600) |
NOT IN (...) | 不在列表中 | goods_num NOT IN (200, 400, 600) |
以下操作符可以用来筛选字符串属性列:
Operator | Condition | Example |
---|---|---|
= | 等于 | goods_name = 'apple' |
!= 或 <> | 不等于 | goods_name != 'apple' |
LIKE | 没有用通配符时,等价于 = | goods_name LIKE 'apple' |
NOT LIKE | 没有用通配符等价于 != | goods_name NOT LIKE 'apple' |
% | 通配符。只和 LIKE 或 NOT LIKE 连用。代表匹配 0 个以上的字符。 | goods_name LIKE '%apple%' |
_ | 使用方式同 % ,区别在于 _ 代表匹配 1 个字符。 | goods_name LIKE 'apple_' |
IN (...) | 在列表中 | goods_num IN ('apple', 'banana') |
NOT IN (...) | 不在列表中 | goods_num NOT IN ('apple', 'banana') |
数据去重 DISTINCT
SELECT DISTINCT column, another_column, ...
FROM tableName
WHERE condition(s);
数据排序 ORDER BY
SELECT column, another_column, ...
FROM tableName
ORDER BY column ASC/DESC;
数据截取 LIMIT
、OFFSET
LIMIT
和 OFFSET
子句通常和 ORDER BY
语句一起使用。
LIMIT
代表数据数量限制,OFFSET
代表数据截取偏移量。
SELECT column, another_column, ...
FROM tableName
ORDER BY column ASC/DESC
LIMIT num_limit OFFSET num_offset;
联表查询
JOINs
类别分为两种 INNER JOIN
和 OUTER JOIN
。
其中 OUTER JOIN
又可以细分为:
LEFT JOIN
RIGHT JOIN
FULL JOIN
SELECT *
FROM tableName
INNER JOIN another_table
ON tableName.id = another_table.id
WHERE condition(s)
ORDER BY column, ... ASC/DESC
LIMIT num_limit OFFSET num_offset;
NULL
字段的处理
之前我们已经接触过 NULL
。 在数据库中,NULL
表达的是 "无" 的概念,或者说没有东西。因为 NULL
的存在,我们需要在编写 SQL
时考虑到某个属性列可能是 NULL
的情况, 这种特殊性会造成编写 SQL
的复杂性,所以没有必要的情况下,我们应该尽量减少 NULL
的使用,让数据中尽可能少出现 NULL
的情况。
如果某个字段你没有填写到数据库,很可能就会出现 NULL
。所已一个常见的方式就是为字段设置默认值,比如 数字的默认值设置为 0
,字符串设置为 ""
字符串。
但是在一些 NULL
表示它本来含义的场景,需要注意是否设置默认值还是保持 NULL
。 (比如, 当你计算一些行的平均值的时候,如果是 0
会参与计算导致平均值差错,是 NULL
则不会参与计算)。
还有一些情况很难避免 NULL
的出现, 比如之前说的 OUTER JOINs
多表连接,A
和 B
有数据差异时,必须用 NULL
来填充。这种情况,可以用 IS NULL
和 IS NOT NULL
来判断在某个字段是否等于 NULL
。
SELECT *
FROM tableName
LEFT JOIN another_table
ON tableName.id = another_table.id
WHERE column IS NOT NULL;
在 SQL
查询中使用表达式
之前我们在 SQL
中的出现 column
(属性名)的地方,我们都只是写上 column
自身。
其实在 SQL
中可以用 column
的地方,都可以用表达式来指定对属性进行一定的计算或处理。
同时,还能使用 AS
命名新的 column
名。
譬如针对 John Lasseter
导演的每部电影每分钟值多少钱,筛选出最高的 3
个电影名和价值:
SELECT Title, (Domestic_sales + International_sales) / Length_minutes AS value FROM movies
INNER JOIN Boxoffice
ON movies.id = Boxoffice.Movie_id
WHERE Director = 'John Lasseter'
ORDER BY value DESC
LIMIT 3;
在查询中进行统计
我们之前只是这样使用:
SELECT column FROM tableName
但实际上 SQL
提供了一些聚合函数以供我们对指定列进行操作。
常用的聚合函数有:
Function | Description |
---|---|
COUNT(*) ,COUNT(column) | 计数!COUNT(*) 统计数据行数,COUNT(column) 统计 column 非 NULL 的行数。 |
MIN(column) | 找 column 最小的一行 |
MAX(column) | 找 column 最大的一行 |
AVG(column) | 对 column 的所有行求平均值 |
SUM(column) | 对 column 的所有行求和 |
譬如,以下形式是对指定列求和:
SELECT SUM(years) FROM movies
关于这些函数的使用方式,要注意的一点是,获取到指定列后再操作。
数据分组 GROUP BY
数据分组,就是按照指定列的相同数据进行分组。
SELECT role_name, work_year FROM emplyees
GROUP BY role_name;
通常情况下聚合函数会与 GROUP BY
分组联用。
譬如,计算角色的平均工作年限:
SELECT role_name, AVG(work_year) FROM emplyees
GROUP BY role_name;
数据子集过滤 HAVING
当我们使用 GROUP BY
对数据分组之后,如果想要进一步筛选,就可以使用 HAVING
。
HAVING
的语法类似于 WHERE
,但二者针对的数据集不同。
SELECT role_name, AVG(work_year) AS avg_work_year FROM emplyees
GROUP BY role_name
HAVING avg_work_year > 3;
SELECT
查询执行顺序
完整的 SELECT
语句如下:
SELECT DISTINCT column, AGG_FUNC(column_or_expression), …
FROM mytable
JOIN another_table
ON mytable.column = another_table.column
WHERE constraint_expression
GROUP BY column
HAVING constraint_expression
ORDER BY column ASC/DESC
LIMIT count OFFSET COUNT;
执行顺序:
FROM
和JOINs
WHERE
GROUP BY
HAVING
SELECT
DISTINCT
ORDER BY
LIMIT
和OFFSET