Skip to content

TIP

SQL 不区分大小写(除了表格名)

但书写 SQL 关键字时,我们推荐用大写形式。

这有助于我们把关键字和 表名、列名区分开,让 SQL 更容易理解。

查询所有列

sql
SELECT *
FROM tableName

查询指定列

sql
SELECT column, another_column, …
FROM tableName

基础条件查询

sql
SELECT column, another_column, …
FROM tableName
WHERE condition
  AND/OR another_condition
  AND/OR

条件 condition 是包含操作符 operator 的表达式。

以下操作符可以用来筛选数字属性列

OperatorConditionExample
= != < <= > >=比较运算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)

以下操作符可以用来筛选字符串属性列

OperatorConditionExample
=等于goods_name = 'apple'
!=<>不等于goods_name != 'apple'
LIKE没有用通配符时,等价于 =goods_name LIKE 'apple'
NOT LIKE没有用通配符等价于 !=goods_name NOT LIKE 'apple'
%通配符。只和 LIKENOT 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

sql
SELECT DISTINCT column, another_column, ...
FROM tableName
WHERE condition(s);

数据排序 ORDER BY

sql
SELECT column, another_column, ...
FROM tableName
ORDER BY column ASC/DESC;

数据截取 LIMITOFFSET

LIMITOFFSET 子句通常和 ORDER BY 语句一起使用

LIMIT 代表数据数量限制,OFFSET 代表数据截取偏移量。

sql
SELECT column, another_column, ...
FROM tableName
ORDER BY column ASC/DESC
LIMIT num_limit OFFSET num_offset;

联表查询

JOINs 类别分为两种 INNER JOINOUTER JOIN

其中 OUTER JOIN 又可以细分为:

  1. LEFT JOIN
  2. RIGHT JOIN
  3. FULL JOIN

sql
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 多表连接,AB 有数据差异时,必须用 NULL 来填充。这种情况,可以用 IS NULLIS NOT NULL 来判断在某个字段是否等于 NULL

sql
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 个电影名和价值:

sql
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;

在查询中进行统计

我们之前只是这样使用:

sql
SELECT column FROM tableName

但实际上 SQL 提供了一些聚合函数以供我们对指定列进行操作。

常用的聚合函数有:

FunctionDescription
COUNT(*)COUNT(column)计数!COUNT(*) 统计数据行数,COUNT(column) 统计 columnNULL 的行数。
MIN(column)column 最小的一行
MAX(column)column 最大的一行
AVG(column)column 的所有行求平均值
SUM(column)column 的所有行求和

譬如,以下形式是对指定列求和:

sql
SELECT SUM(years) FROM movies

关于这些函数的使用方式,要注意的一点是,获取到指定列后再操作

数据分组 GROUP BY

数据分组,就是按照指定列的相同数据进行分组。

sql
SELECT role_name, work_year FROM emplyees
GROUP BY role_name;

通常情况下聚合函数会与 GROUP BY 分组联用。

譬如,计算角色的平均工作年限:

sql
SELECT role_name, AVG(work_year) FROM emplyees
GROUP BY role_name;

数据子集过滤 HAVING

当我们使用 GROUP BY 对数据分组之后,如果想要进一步筛选,就可以使用 HAVING

HAVING 的语法类似于 WHERE,但二者针对的数据集不同

sql
SELECT role_name, AVG(work_year) AS avg_work_year FROM emplyees
GROUP BY role_name
HAVING avg_work_year > 3;

SELECT 查询执行顺序

完整的 SELECT 语句如下:

sql
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;

执行顺序:

  1. FROMJOINs
  2. WHERE
  3. GROUP BY
  4. HAVING
  5. SELECT
  6. DISTINCT
  7. ORDER BY
  8. LIMITOFFSET