SELECT
[ALL | DISTINCT | DISTINCTROW ]
select_expr [, select_expr] ...
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
[HAVING where_condition]
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
[LIMIT {[offset,] row_count | row_count OFFSET offset}]
1. SELECT 语句基础
1.1 SELECT语句
# 语法
SELECT 列名 FROM 表名;
# 示例
mysql> SELECT DEPTNO, DNAME FROM DEPT;
+--------+------------+
| DEPTNO | DNAME |
+--------+------------+
| 10 | ACCOUNTING |
| 20 | RESEARCH |
| 30 | SALES |
| 40 | OPERATIONS |
+--------+------------+
1.2 WHERE 语句
SELECT 语句通过 WHERE 子句满足查询指定条件的数据。
# 语法
SELECT 列名 FROM 表名 WHERE 条件;
# 示例
# 查询 product_type 列为 clothes 的所有商品
mysql> SELECT product_id, product_name, product_type FROM tbl_product WHERE product_type='clothes';
+------------+----------------+--------------+
| product_id | product_name | product_type |
+------------+----------------+--------------+
| 0001 | T-shirt | clothes |
| 0003 | sports T-shirt | clothes |
+------------+----------------+--------------+
# 查询销售价格大于等于1000的衣服
mysql> SELECT
-> product_id, product_name, product_type, sale_price
-> FROM tbl_product
-> WHERE product_type='clothes' and sale_price>=1000;
+------------+----------------+--------------+------------+
| product_id | product_name | product_type | sale_price |
+------------+----------------+--------------+------------+
| 0001 | T-shirt | clothes | 1000 |
| 0003 | sports T-shirt | clothes | 4000 |
+------------+----------------+--------------+------------+
1.2 相关法则
- 星号(*)代表全部列的意思。
- SQL中可以随意使用换行符,不影响语句执行(但不可插入空行)。
- 字符串需要使用单引号(
'
)或者双引号("
)括起来。 - 在SELECT语句中使用
DISTINCT
可以删除重复行。 - 注释
- 单行注释:
--
或者#
- 多行注释:
/* */
。
- 单行注释:
示例
# 查询 价格在1000~4000的所有商品信息
mysql> SELECT * FROM tbl_product WHERE sale_price BETWEEN 1000 AND 4000;
+------------+----------------+--------------+------------+----------------+---------------+
| product_id | product_name | product_type | sale_price | purchase_price | register_date |
+------------+----------------+--------------+------------+----------------+---------------+
| 0001 | T-shirt | clothes | 1000 | 500 | 2009-09-20 |
| 0003 | sports T-shirt | clothes | 4000 | 2800 | NULL |
| 0004 | kitchen knife | kitchenware | 3000 | 2800 | 2009-09-20 |
+------------+----------------+--------------+------------+----------------+---------------+
# 查询 商品类别
mysql> SELECT DISTINCT product_type FROM tbl_product;
+-----------------+
| product_type |
+-----------------+
| clothes |
| Office supplies |
| kitchenware |
+-----------------+
2. 运算符
2.1 算术运算符
含义 | 运算符 |
---|---|
+、-、*、/ | 加法、减法、乘法、除法 |
%,MOD | 模 |
SELECT
product_id,
product_name,
sale_price - purchase_price AS profit
FROM tbl_product
WHERE purchase_price IS NOT NULL;
+------------+-----------------+--------+
| product_id | product_name | profit |
+------------+-----------------+--------+
| 0001 | T-shirt | 500 |
| 0002 | puncher | 180 |
| 0003 | sports T-shirt | 1200 |
| 0004 | kitchen knife | 200 |
| 0005 | pressure cooker | 1800 |
| 0007 | grater | 90 |
+------------+-----------------+--------+
2.2 位运算符
Name | Description |
---|---|
& | 按位与 |
| | 按位或 |
^ | 按位异或 |
~ | 按位取反 |
<<、>> | 左移、右移 |
mysql> SELECT 3 & 2;
+-------+
| 3 & 2 |
+-------+
| 2 |
+-------+
2.3 逻辑运算符
Name | Description |
---|---|
>、<、=、>=、<= | 大于、小于、等于、大于等于、小于等于 |
<>、!= | 不等于 |
&&,AND | 逻辑与 |
||,OR | 逻辑或 |
NOT,! | 逻辑非 |
# 查询 价格在1000~4000的所有商品信息
SELECT * FROM tbl_product
WHERE sale_price >= 1000 AND sale_price <= 4000;
+------------+----------------+--------------+------------+----------------+---------------+
| product_id | product_name | product_type | sale_price | purchase_price | register_date |
+------------+----------------+--------------+------------+----------------+---------------+
| 0001 | T-shirt | clothes | 1000 | 500 | 2009-09-20 |
| 0003 | sports T-shirt | clothes | 4000 | 2800 | NULL |
| 0004 | kitchen knife | kitchenware | 3000 | 2800 | 2009-09-20 |
+------------+----------------+--------------+------------+----------------+---------------+
# 查询 价格不在1000~4000范围的所有商品信息
SELECT * FROM tbl_product
WHERE NOT (sale_price >= 1000 AND sale_price <= 4000);
mysql> SELECT * FROM tbl_product
-> WHERE NOT (sale_price >= 1000 AND sale_price <= 4000);
+------------+-----------------+-----------------+------------+----------------+---------------+
| product_id | product_name | product_type | sale_price | purchase_price | register_date |
+------------+-----------------+-----------------+------------+----------------+---------------+
| 0002 | puncher | Office supplies | 500 | 320 | 2009-09-11 |
| 0005 | pressure cooker | kitchenware | 6800 | 5000 | 2009-01-15 |
| 0006 | fork | kitchenware | 500 | NULL | 2009-09-20 |
| 0007 | grater | kitchenware | 880 | 790 | 2008-04-28 |
| 0008 | ballpoint | Office supplies | 100 | NULL | 2009-11-11 |
+------------+-----------------+-----------------+------------+----------------+---------------+
含有NULL时的真值:NULL的真值结果既不为真,也不为假,因为并不知道这样一个值。那该如何表示呢?
这时真值是除真假之外的第三种值——不确定(UNKNOWN)。一般的逻辑运算并不存在这第三种值。SQL 之外的语言也基本上只使用真和假这两种真值。与通常的逻辑运算被称为二值逻辑相对,只有 SQL 中的逻辑运算被称为三值逻辑。

2.4 常用法则
- SELECT 子句中可以使用常数或者表达式。
- 使用逻辑运算符时一定要注意不等号和等号的位置。
- 字符串类型的数据原则上按照字典顺序进行排序,不能与数字的大小顺序混淆。
- 希望选取
NULL
记录时,需要在条件表达式中使用IS NULL
运算符。希望选取不是NULL
的记录时,需要在条件表达式中使用IS NOT NULL
运算符。
SELECT
product_name, sale_price, sale_price * 2 AS "sale_price x2"
FROM tbl_product;
+-----------------+------------+---------------+
| product_name | sale_price | sale_price x2 |
+-----------------+------------+---------------+
| T-shirt | 1000 | 2000 |
| puncher | 500 | 1000 |
| sports T-shirt | 4000 | 8000 |
| kitchen knife | 3000 | 6000 |
| pressure cooker | 6800 | 13600 |
| fork | 500 | 1000 |
| grater | 880 | 1760 |
| ballpoint | 100 | 200 |
+-----------------+------------+---------------+
# 选取 purchase_price 为 NULL 的记录
SELECT product_name, purchase_price
FROM tbl_product
WHERE purchase_price IS NULL;
+--------------+----------------+
| product_name | purchase_price |
+--------------+----------------+
| fork | NULL |
| ballpoint | NULL |
+--------------+----------------+
2.5 通过括号优先处理
“商品种类为办公用品”并且“登记日期是 2009 年 9 月 11 日或者 2009 年 9 月 20 日”,理想结果为“打孔器”,但当你输入以下信息时,会得到错误结果
/*
将查询条件原封不动地写入条件表达式,会得到错误结果
实际上条件变成了
(product_type = 'Office supplies' AND register_date = '2009-09-11') OR register_date = '2009-09-20';
*/
SELECT product_name, product_type, register_date
FROM tbl_product
WHERE product_type = 'Office supplies'
AND register_date = '2009-09-11'
OR register_date = '2009-09-20';
+---------------+-----------------+---------------+
| product_name | product_type | register_date |
+---------------+-----------------+---------------+
| T-shirt | clothes | 2009-09-20 |
| puncher | Office supplies | 2009-09-11 |
| kitchen knife | kitchenware | 2009-09-20 |
| fork | kitchenware | 2009-09-20 |
+---------------+-----------------+---------------+
错误的原因是 AND 运算符优先于 OR 运算符,想要优先执行OR运算,可以使用括号:
SELECT product_name, product_type, register_date
FROM tbl_product
WHERE product_type = 'Office supplies'
AND (register_date = '2009-09-11' OR register_date = '2009-09-20');
+--------------+-----------------+---------------+
| product_name | product_type | register_date |
+--------------+-----------------+---------------+
| puncher | Office supplies | 2009-09-11 |
+--------------+-----------------+---------------+
练习题-第一部分
-
编写一条SQL语句,从 tbl_product 表中选取出“登记日期(register在2009年4月28日之后”的商品,查询结果要包含 product_name 和register_date 两列。
SELECT product_name, register_date FROM tbl_product WHERE register_date > '2009-4-28'; +---------------+---------------+ | product_name | register_date | +---------------+---------------+ | T-shirt | 2009-09-20 | | puncher | 2009-09-11 | | kitchen knife | 2009-09-20 | | fork | 2009-09-20 | | ballpoint | 2009-11-11 | +---------------+---------------+
-
请说出对 product 表执行如下3条 SELECT 语句时的返回结果。
# 1. 查询 purchase_price 为空的商品信息 SELECT * FROM tbl_product WHERE purchase_price = NULL; # 2. 查询结果是空的 SELECT * FROM tbl_product WHERE purchase_price <> NULL; # 正确写法 查询 purchase_price 不为空的商品信息 SELECT * FROM tbl_product WHERE purchase_price IS NULL; # 3. 查询结果是空的 # 正确写法 查询 product_name 不为空的商品信息 SELECT * FROM tbl_product WHERE product_name IS NOT NULL;
-
代码清单2-22(2-2节)中的 SELECT 语句能够从 tbl_product 表中取出“销售单价(sale_price)比进货单价(purchase_price)高出500日元以上”的商品。请写出两条可以得到相同结果的 SELECT 语句。执行结果如下所示。
SELECT product_name, sale_price, purchase_price FROM tbl_product WHERE sale_price - purchase_price >= 500; +-----------------+------------+----------------+ | product_name | sale_price | purchase_price | +-----------------+------------+----------------+ | T-shirt | 1000 | 500 | | sports T-shirt | 4000 | 2800 | | pressure cooker | 6800 | 5000 | +-----------------+------------+----------------+
-
请写出一条 SELECT 语句,从 tbl_product 表中选取出满足“销售单价打九折之后利润高于100日元的办公用品和厨房用具”条件的记录。查询结果要包括 product_name 列、product_type 列以及销售单价打九折之后的利润(别名设定为 profit)。
提示:销售单价打九折,可以通过saleprice列的值乘以0.9获得,利润可以通过该值减去purchase_price列的值获得。
SELECT product_name, product_type, (sale_price * 0.9 - purchase_price) AS profit FROM tbl_product WHERE (sale_price * 0.9 - purchase_price) >= 100 AND product_type IN('Office supplies', 'kitchenware'); +-----------------+-----------------+--------+ | product_name | product_type | profit | +-----------------+-----------------+--------+ | puncher | Office supplies | 130.0 | | pressure cooker | kitchenware | 1120.0 | +-----------------+-----------------+--------+
3. 对表进行聚合查询
3.1 聚合函数
SQL中用于汇总的函数叫做聚合函数(或叫统计函数、分组函数、组函数)。以下五个是最常用的聚合函数:
- COUNT:计算表中的记录数(行数)
- SUM:计算表中数值列中数据的合计值
- AVG:计算表中数值列中数据的平均值
- MAX:求出表中任意列中数据的最大值
- MIN:求出表中任意列中数据的最小值
# 查询 sale_price 大于 1000 的商品数量
SELECT COUNT(*) FROM tbl_product WHERE sale_price > 1000;
+----------+
| COUNT(*) |
+----------+
| 3 |
+----------+
# 查询 总的 sale_price 和 总的 purchase_price
SELECT SUM(sale_price 和), SUM(purchase_price) FROM tbl_product;
+-----------------+---------------------+
| SUM(sale_price) | SUM(purchase_price) |
+-----------------+---------------------+
| 16780 | 12210 |
+-----------------+---------------------+
# 查询 最大 sale_price、最小 sale_price、最大 purchase_price、最小 purchase_price
SELECT MAX(sale_price), MIN(sale_price), MAX(purchase_price), MIN(purchase_price) FROM tbl_product;
+-----------------+-----------------+---------------------+---------------------+
| MAX(sale_price) | MIN(sale_price) | MAX(purchase_price) | MIN(purchase_price) |
+-----------------+-----------------+---------------------+---------------------+
| 6800 | 100 | 5000 | 320 |
+-----------------+-----------------+---------------------+---------------------+
# 查询 平均 sale_price 和平均 purchase_price
SELECT AVG(sale_price), AVG(purchase_price) FROM tbl_product;
+-----------------+---------------------+
| AVG(sale_price) | AVG(purchase_price) |
+-----------------+---------------------+
| 2097.5000 | 2035.0000 |
+-----------------+---------------------+
- 使用聚合函数删除重复值
# 计算去除重复数据后的数据行数
SELECT COUNT(DISTINCT product_type)
FROM tbl_product;
+------------------------------+
| COUNT(DISTINCT product_type) |
+------------------------------+
| 3 |
+------------------------------+
# 是否使用DISTINCT时的动作差异(SUM函数),因为 sale_price 有两个 500,所以去重后求和会少 500
SELECT SUM(sale_price), SUM(DISTINCT sale_price)
FROM tbl_product;
+-----------------+--------------------------+
| SUM(sale_price) | SUM(DISTINCT sale_price) |
+-----------------+--------------------------+
| 16780 | 16280 |
+-----------------+--------------------------+
3.2 常用法则
-
COUNT 函数的结果根据参数的不同而不同。
- COUNT(*) :得到包含 NULL 的数据行数
- COUNT(<列名>) :得到不包含 NULL 的数据行数。
-
聚合函数会将 NULL 排除在外。但 COUNT(*) 例外,并不会排除 NULL 。
-
MAX / MIN 函数几乎适用于所有数据类型的列,对于字符串类型按字典顺序越往后越大。 SUM / AVG 函数只适用于数值类型的列。
-
想要计算值的种类数量时,可以在 COUNT 函数的参数中使用 DISTINCT 。
-
在聚合函数的参数中使用 DISTINCT,可以删除重复数据。
4. 对表进行分组
4.1 GROUP BY 语句
之前使用聚合函数都是会整个表的数据进行处理。🍰
当想将进行分组汇总时(将现有的数据按照某列来汇总统计),就需要使用 GROUP BY。
SELECT
[ALL | DISTINCT | DISTINCTROW ]
select_expr [, select_expr] ...
[FROM table_references
[WHERE where_condition]
[GROUP BY {col_name | expr | position}, ... [WITH ROLLUP]]
# 按照商品种类,统计数据行数
SELECT product_type, COUNT(*)
FROM tbl_product
GROUP BY product_type;
+-----------------+----------+
| product_type | COUNT(*) |
+-----------------+----------+
| clothes | 2 |
| Office supplies | 2 |
| kitchenware | 4 |
+-----------------+----------+
# 不含GROUP BY
ERROR 1140 (42000): In aggregated query without GROUP BY, expression #1 of SELECT list contains nonaggregated column 'shop.tbl_product.product_type'; this is incompatible with sql_mode=only_full_group_by
聚合键中包含NULL时
将进货单价(purchase_price)作为聚合键举例:将值为 NULL 的分到一个组里面。
SELECT purchase_price, COUNT(*)
FROM tbl_product
GROUP BY purchase_price;
+----------------+----------+
| purchase_price | COUNT(*) |
+----------------+----------+
| 500 | 1 |
| 320 | 1 |
| 2800 | 2 |
| 5000 | 1 |
| NULL | 2 |
| 790 | 1 |
+----------------+----------+
GROUP BY书写位置
GROUP BY的子句书写顺序有严格要求,不按要求会导致SQL无法正常执行,目前出现过的子句顺序为:
1 SELECT → 2 FROM → 3 WHERE → 4 GROUP BY
其中前三项用于筛选数据,GROUP BY对筛选出的数据进行处理
执行顺序为:1 FROM → 2 WHERE → 3 GROUP BY → 4 SELECT
WHERE子句中使用GROUP BY
SELECT purchase_price, COUNT(*)
FROM tbl_product
WHERE product_type = 'clothes'
GROUP BY purchase_price;
+----------------+----------+
| purchase_price | COUNT(*) |
+----------------+----------+
| 500 | 1 |
| 2800 | 1 |
+----------------+----------+
4.2 常见错误
在使用聚合函数及GROUP BY子句时,经常出现的错误有:
-
在聚合函数的 SELECT 子句中写了聚合健以外的列 使用 COUNT 等聚合函数时,SELECT 子句中如果出现列名,只能是 GROUP BY 子句中指定的列名(也就是聚合键)。
SLELECT product_name FROM tbl_product GROUP BY product_type; ERROR 1064 (42000): You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'SLELECT product_name FROM tbl_product GROUP BY product_type' at line 1
-
在MySQL里面GROUP BY 子句中是可以使用 SELECT 子句通过 AS 来定义的别名但是不推荐。可能是MySQL底层多了优化。🐶
在Oracle、Hive等数据库里面GROUP BY 是不能使用别名的。因为SELECT 子句在 GROUP BY 子句后执行。
SELECT product_type AS p_type, COUNT(*) FROM tbl_product GROUP BY p_type; +-----------------+----------+ | p_type | COUNT(*) | +-----------------+----------+ | clothes | 2 | | Office supplies | 2 | | kitchenware | 4 | +-----------------+----------+
-
在 WHERE 中不能使用聚合函数。
原因是聚合函数的使用前提是结果集已经确定,而 WHERE 还处于确定结果集的过程中,所以相互矛盾会引发错误。
如果想指定条件,可以在 SELECT,HAVING(下面马上会讲)以及 ORDER BY 子句中使用聚合函数。
5. 为聚合结果指定条件
5.1 用HAVING得到特定分组

这里用 WHERE 不可行,因为 WHERE 子句只能指定记录(行)的条件,而不能用来指定组(列)的条件(例如,“数据行数为 2 行”或者“平均值为 500”等)。
可以在 GROUP BY 后使用 HAVING 子句。
5.2 HAVING特点
HAVING 子句用于对分组进行过滤,可以使用数字、聚合函数和 GROUP BY 中指定的列名(聚合键)。
# 数字 聚合函数
SELECT product_type, COUNT(*) AS `count`
FROM tbl_product
GROUP BY product_type
HAVING `count` = 2;
+-----------------+-------+
| product_type | count |
+-----------------+-------+
| clothes | 2 |
| Office supplies | 2 |
+-----------------+-------+
# 错误形式(因为 product_name 不包含在 GROUP BY 聚合键中)
SELECT product_type, COUNT(*) AS `count`
FROM tbl_product
GROUP BY product_type
HAVING sale_price >= 1000;
# ERROR 1054 (42S22): Unknown column 'sale_price' in 'having clause'
6. 对查询结果进行排序
6.1 ORDER BY 子句
SQL中的执行结果是随机排列的,当需要按照特定顺序排序时,可已使用ORDER BY子句。
SELECT
select_expr [, select_expr] ...
[FROM table_references
[ORDER BY {col_name | expr | position}
[ASC | DESC], ... [WITH ROLLUP]]
默认为升序排列(ASC),降序排列为 DESC
# 按 purchase_price 升序排列
SELECT product_id, product_name, sale_price, purchase_price
FROM tbl_product
WHERE purchase_price >= 500
ORDER BY purchase_price;
+------------+-----------------+------------+----------------+
| product_id | product_name | sale_price | purchase_price |
+------------+-----------------+------------+----------------+
| 0001 | T-shirt | 1000 | 500 |
| 0007 | grater | 880 | 790 |
| 0003 | sports T-shirt | 4000 | 2800 |
| 0004 | kitchen knife | 3000 | 2800 |
| 0005 | pressure cooker | 6800 | 5000 |
+------------+-----------------+------------+----------------+
# 按 purchase_price 升序排列,purchase_price相同时,按 sale_price 升序排列
SELECT product_id, product_name, sale_price, purchase_price
FROM tbl_product
WHERE purchase_price >= 500
ORDER BY purchase_price ASC, sale_price ASC;
+------------+-----------------+------------+----------------+
| product_id | product_name | sale_price | purchase_price |
+------------+-----------------+------------+----------------+
| 0001 | T-shirt | 1000 | 500 |
| 0007 | grater | 880 | 790 |
| 0004 | kitchen knife | 3000 | 2800 |
| 0003 | sports T-shirt | 4000 | 2800 |
| 0005 | pressure cooker | 6800 | 5000 |
+------------+-----------------+------------+----------------+
6.2 ORDER BY 中可使用别名
前文讲 GROUP BY 中提到,GROUP BY 子句中不能使用 SELECT 子句定义的别名,但是在 ORDER BY 子句中却可以使用别名。
为什么在GROUP BY中不可以而在ORDER BY中可以呢?
这是因为SQL在使用 HAVING 子句时 SELECT 语句的执行顺序为:
1 FROM → 2 WHERE → 3 GROUP BY → 4 HAVING → 5 SELECT → 6 ORDER BY。
其中 SELECT 在 GROUP BY 后 ORDER BY 前执行的。也就是说,当在 ORDER BY中使用别名时,已经知道了 SELECT 设置的别名存在,但是在GROUP BY 中使用别名时还不知道别名的存在,所以能在 ORDER BY 中可以使用别名,但是不能在 GROUP BY中使用别名。
练习题-第二部分
- 请指出下述 SELECT 语句中所有的语法错误。
SELECT product_id, SUM(product_name)
FROM tbl_product
GROUP BY product_type
WHERE register_date > '2009-09-01';
错误1:SUM(product_name)
,不能使用中文括号,SUM 对 product_name 字符类型求和没有意义。
错误2:SELECT product_id, SUM(product_name)
,SELECT 子句,只能使用聚合键,不能使用其他列名
错误3:GROUP BY product_type WHERE register_date > '2009-09-01'
,WHERE 子句应该在 FROM 子句后 GROUP BY 子句前。
正确写法
# 按照 商品种类 统计 注册日期在 2009-09-01 之后 的商品
SELECT product_type, COUNT(*)
FROM tbl_product
WHERE register_date > '2009-09-01'
GROUP BY product_type;
+-----------------+----------+
| product_type | COUNT(*) |
+-----------------+----------+
| clothes | 1 |
| Office supplies | 2 |
| kitchenware | 2 |
+-----------------+----------+
- 请编写一条 SELECT 语句,求出销售单价(
sale_price
列)合计值大于进货单价(purchase_price
列)合计值1.5倍的商品种类。执行结果如下所示。
product_type | sum | sum
-------------+------+------
clothes | 5000 | 3300
Office supplies | 600 | 320
思路:先查出按 product_type分组,每个商品类别的总销售单价和总进货单价,然后使用having对分组结果过滤。
# 每个商品类别的总销售单价和总进货单价
SELECT product_type, SUM(sale_price) AS `sum`, SUM(purchase_price) AS `sum`
FROM tbl_product
GROUP BY product_type;
+-----------------+-------+------+
| product_type | sum | sum |
+-----------------+-------+------+
| clothes | 5000 | 3300 |
| Office supplies | 600 | 320 |
| kitchenware | 11180 | 8590 |
+-----------------+-------+------+
# 使用having对分组结果过滤
SELECT product_type, SUM(sale_price) AS `sum`, SUM(purchase_price) AS `sum`
FROM tbl_product
GROUP BY product_type
HAVING SUM(sale_price) > SUM(purchase_price) * 1.5;
+-----------------+------+------+
| product_type | sum | sum |
+-----------------+------+------+
| clothes | 5000 | 3300 |
| Office supplies | 600 | 320 |
+-----------------+------+------+
- 此前我们曾经使用SELECT语句选取出了product(商品)表中的全部记录。当时我们使用了ORDERBY子句来指定排列顺序,但现在已经无法记起当时如何指定的了。请根据下列执行结果,思考ORDERBY子句的内容。

-
发现 product_id、product_name、product_type、sale_price、purchase_price都是无序的,register_date 是降序。所以应该是首先对 register_date 进行降序排列。
-
接下来重点关注 register_date 有相同时的值 2009-09-20 的那三行数据。发现product_id、product_name、product_type无序,sale_price 和 purchase_price都是升序的。
+------------+-----------------+-----------------+------------+----------------+---------------+
| product_id | product_name | product_type | sale_price | purchase_price | register_date |
+------------+-----------------+-----------------+------------+----------------+---------------+
| 0006 | fork | kitchenware | 500 | NULL | 2009-09-20 |
| 0001 | T-shirt | clothes | 1000 | 500 | 2009-09-20 |
| 0004 | kitchen knife | kitchenware | 3000 | 2800 | 2009-09-20 |
😂 太菜了,对比两种情况,结果都一样,NULL值被当做最小值,排到后面了。。结果如下:
SELECT *
FROM tbl_product
ORDER BY register_date DESC, sale_price ASC;
SELECT *
FROM tbl_product
ORDER BY register_date DESC, purchase_price ASC;
+------------+-----------------+-----------------+------------+----------------+---------------+
| product_id | product_name | product_type | sale_price | purchase_price | register_date |
+------------+-----------------+-----------------+------------+----------------+---------------+
| 0008 | ballpoint | Office supplies | 100 | NULL | 2009-11-11 |
| 0006 | fork | kitchenware | 500 | NULL | 2009-09-20 |
| 0001 | T-shirt | clothes | 1000 | 500 | 2009-09-20 |
| 0004 | kitchen knife | kitchenware | 3000 | 2800 | 2009-09-20 |
| 0002 | puncher | Office supplies | 500 | 320 | 2009-09-11 |
| 0005 | pressure cooker | kitchenware | 6800 | 5000 | 2009-01-15 |
| 0007 | grater | kitchenware | 880 | 790 | 2008-04-28 |
| 0003 | sports T-shirt | clothes | 4000 | 2800 | NULL |
+------------+-----------------+-----------------+------------+----------------+---------------+