Update ch03: 复杂一点的查询.md

This commit is contained in:
mba1398
2021-07-07 15:05:30 +08:00
committed by GitHub
parent 0c35485f7b
commit c4d4c24ba2

View File

@@ -747,4 +747,682 @@ COALESCE(NULL, NULL, '2020-11-01') AS col_3;
## 3.4.1 什么是谓词
谓词就是
谓词就是返回值为真值的函数。包括`TRUE / FALSE / UNKNOWN`
谓词主要有以下几个:
* LIKE
* BETWEEN
* IS NULL、IS NOT NULL
* IN
* EXISTS
##
## 3.4.2 LIKE谓词 -- 用于字符串的部分一致查询
当需要进行字符串的部分一致查询时需要使用该谓词。
部分一致大体可以分为前方一致、中间一致和后方一致三种类型。
首先我们来创建一张表
```sql
-- DDL :创建表
CREATE TABLE samplelike
( strcol VARCHAR(6) NOT NULL,
PRIMARY KEY (strcol)
samplelike);
-- DML :插入数据
START TRANSACTION; -- 开始事务
INSERT INTO samplelike (strcol) VALUES ('abcddd');
INSERT INTO samplelike (strcol) VALUES ('dddabc');
INSERT INTO samplelike (strcol) VALUES ('abdddc');
INSERT INTO samplelike (strcol) VALUES ('abcdd');
INSERT INTO samplelike (strcol) VALUES ('ddabc');
INSERT INTO samplelike (strcol) VALUES ('abddc');
COMMIT; -- 提交事务
SELECT * FROM samplelike;
+--------+
| strcol |
+--------+
| abcdd  |
| abcddd |
| abddc  |
| abdddc |
| ddabc  |
| dddabc |
+--------+
6 rows in set (0.00 sec)
```
* 前方一致选取出“dddabc”
前方一致即作为查询条件的字符串这里是“ddd”与查询对象字符串起始部分相同。
```sql
SELECT *
FROM samplelike
WHERE strcol LIKE 'ddd%';
+--------+
| strcol |
+--------+
| dddabc |
+--------+
1 row in set (0.00 sec)
```
其中的`%`是代表“零个或多个任意字符串”的特殊符号本例中代表“以ddd开头的所有字符串”。
* 中间一致选取出“abcddd”“dddabc”“abdddc”
中间一致即查询对象字符串中含有作为查询条件的字符串,无论该字符串出现在对象字
符串的最后还是中间都没有关系。
```sql
SELECT *
FROM samplelike
WHERE strcol LIKE '%ddd%';
+--------+
| strcol |
+--------+
| abcddd |
| abdddc |
| dddabc |
+--------+
3 rows in set (0.00 sec)
```
* 后方一致选取出“abcddd“
后方一致即作为查询条件的字符串这里是“ddd”与查询对象字符串的末尾部分相同。
```sql
SELECT *
FROM samplelike
WHERE strcol LIKE '%ddd';
+--------+
| strcol |
+--------+
| abcddd |
+--------+
1 row in set (0.00 sec)
```
综合如上三种类型的查询可以看出,查询条件最宽松,也就是能够取得最多记录的是`中间一致`。这是因为它同时包含前方一致和后方一致的查询结果。
* `_`下划线匹配任意 1 个字符
使用 _下划线来代替 %,与 % 不同的是,它代表了“任意 1 个字符”。
```sql
SELECT *
FROM samplelike
WHERE strcol LIKE 'abc__';
+--------+
| strcol |
+--------+
| abcdd  |
+--------+
1 row in set (0.00 sec)
```
##
## 3.4.3 BETWEEN谓词 -- 用于范围查询
使用 BETWEEN 可以进行范围查询。该谓词与其他谓词或者函数的不同之处在于它使用了 3 个参数。
```sql
-- 选取销售单价为100 1000元的商品
SELECT product_name, sale_price
FROM product
WHERE sale_price BETWEEN 100 AND 1000;
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| T恤          |       1000 |
|        |        500 |
|          |        500 |
|        |        880 |
|        |        100 |
+--------------+------------+
5 rows in set (0.00 sec)
```
BETWEEN 的特点就是结果中会包含 100 和 1000 这两个临界值,也就是闭区间。如果不想让结果中包含临界值,那就必须使用 < 和 >。
```sql
SELECT product_name, sale_price
FROM product
WHERE sale_price > 100
AND sale_price < 1000;
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
|        |        500 |
|          |        500 |
|        |        880 |
+--------------+------------+
3 rows in set (0.00 sec)
```
##
## 3.4.4 IS NULL、 IS NOT NULL -- 用于判断是否为NULL
为了选取出某些值为 NULL 的列的数据,不能使用 =而只能使用特定的谓词IS NULL。
```sql
SELECT product_name, purchase_price
FROM product
WHERE purchase_price IS NULL;
+--------------+----------------+
| product_name | purchase_price |
+--------------+----------------+
|          |           NULL |
|        |           NULL |
+--------------+----------------+
2 rows in set (0.00 sec)
```
与此相反,想要选取 NULL 以外的数据时需要使用IS NOT NULL。
```sql
SELECT product_name, purchase_price
FROM product
WHERE purchase_price IS NOT NULL;
+--------------+----------------+
| product_name | purchase_price |
+--------------+----------------+
| T恤          |            500 |
|        |            320 |
| T恤      |           2800 |
|          |           2800 |
|        |           5000 |
|        |            790 |
+--------------+----------------+
6 rows in set (0.00 sec)
```
##
## 3.4.5 IN谓词 -- OR的简便用法
多个查询条件取并集时可以选择使用`or`语句。
```sql
-- 通过OR指定多个进货单价进行查询
SELECT product_name, purchase_price
FROM product
WHERE purchase_price = 320
OR purchase_price = 500
OR purchase_price = 5000;
+--------------+----------------+
| product_name | purchase_price |
+--------------+----------------+
| T恤          |            500 |
|        |            320 |
|        |           5000 |
+--------------+----------------+
3 rows in set (0.00 sec)
```
虽然上述方法没有问题,但还是存在一点不足之处,那就是随着希望选取的对象越来越多, SQL 语句也会越来越长,阅读起来也会越来越困难。这时, 我们就可以使用IN 谓词
`IN(值1, 值2, 值3, ......)来替换上述 SQL 语句。
```sql
SELECT product_name, purchase_price
FROM product
WHERE purchase_price IN (320, 500, 5000);
+--------------+----------------+
| product_name | purchase_price |
+--------------+----------------+
| T恤          |            500 |
| 打孔器       |            320 |
| 高压锅       |           5000 |
+--------------+----------------+
3 rows in set (0.00 sec)
```
上述语句简洁了很多,可读性大幅提高。
反之,希望选取出“进货单价不是 320 元、 500 元、 5000 元”的商品时可以使用否定形式NOT IN来实现。
```sql
SELECT product_name, purchase_price
FROM product
WHERE purchase_price NOT IN (320, 500, 5000);
+--------------+----------------+
| product_name | purchase_price |
+--------------+----------------+
| 运动T恤      |           2800 |
| 菜刀         |           2800 |
| 擦菜板       |            790 |
+--------------+----------------+
3 rows in set (0.00 sec)
```
需要注意的是在使用IN 和 NOT IN 时是无法选取出NULL数据的。
实际结果也是如此,上述两组结果中都不包含进货单价为 NULL 的叉子和圆珠笔。 NULL 只能使用 IS NULL 和 IS NOT NULL 来进行判断。
##
## 3.4.6 使用子查询作为IN谓词的参数
* IN和子查询
IN 谓词NOT IN 谓词)具有其他谓词所没有的用法,那就是可以使用子查询作为其参数。我们已经在 5-2 节中学习过了,子查询就是 SQL内部生成的表因此也可以说“能够将表作为 IN 的参数”。同理,我们还可以说“能够将视图作为 IN 的参数”。
在此,我们创建一张新表`shopproduct`显示出哪些商店销售哪些商品。
```sql
-- DDL :创建表
DROP TABLE IF EXISTS shopproduct;
CREATE TABLE shopproduct
( shop_id CHAR(4) NOT NULL,
 shop_name VARCHAR(200) NOT NULL,
product_id CHAR(4) NOT NULL,
  quantity INTEGER NOT NULL,
PRIMARY KEY (shop_id, product_id) -- 指定主键
);
-- DML :插入数据
START TRANSACTION; -- 开始事务
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0001', 30);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0002', 50);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000A', '东京', '0003', 15);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0002', 30);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0003', 120);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0004', 20);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0006', 10);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000B', '名古屋', '0007', 40);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0003', 20);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0004', 50);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0006', 90);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000C', '大阪', '0007', 70);
INSERT INTO shopproduct (shop_id, shop_name, product_id, quantity) VALUES ('000D', '福冈', '0001', 100);
COMMIT; -- 提交事务
SELECT * FROM shopproduct;
+---------+-----------+------------+----------+
| shop_id | shop_name | product_id | quantity |
+---------+-----------+------------+----------+
| 000A    | 东京      | 0001       |       30 |
| 000A    | 东京      | 0002       |       50 |
| 000A    | 东京      | 0003       |       15 |
| 000B    | 名古屋      | 0002       |       30 |
| 000B    | 名古屋      | 0003       |      120 |
| 000B    | 名古屋      | 0004       |       20 |
| 000B    | 名古屋      | 0006       |       10 |
| 000B    | 名古屋      | 0007       |       40 |
| 000C    | 大阪      | 0003       |       20 |
| 000C    | 大阪      | 0004       |       50 |
| 000C    | 大阪      | 0006       |       90 |
| 000C    | 大阪      | 0007       |       70 |
| 000D    | 福冈      | 0001       |      100 |
+---------+-----------+------------+----------+
13 rows in set (0.00 sec)
```
由于单独使用商店编号shop_id或者商品编号product_id不能区分表中每一行数据
,因此指定了 2 列作为主键primary key对商店和商品进行组合用来唯一确定每一行数据。
假设我么需要取出大阪在售商品的销售单价,该如何实现呢?
第一步,取出大阪门店的在售商品 `product_id ;
第二步,取出大阪门店在售商品的销售单价 `sale_price
```sql
-- step1取出大阪门店的在售商品 `product_id`
SELECT product_id
FROM shopproduct
WHERE shop_id = '000C';
+------------+
| product_id |
+------------+
| 0003       |
| 0004       |
| 0006       |
| 0007       |
+------------+
4 rows in set (0.00 sec)
```
上述语句取出了大阪门店的在售商品编号,接下来,我么可以使用上述语句作为第二步的查询条件来使用了。
```sql
-- step2取出大阪门店在售商品的销售单价 `sale_price`
SELECT product_name, sale_price
FROM product
WHERE product_id IN (SELECT product_id
FROM shopproduct
WHERE shop_id = '000C');
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| 运动T恤      |       4000 |
| 菜刀         |       3000 |
| 叉子         |        500 |
| 擦菜板       |        880 |
+--------------+------------+
4 rows in set (0.00 sec)
```
根据第5章学习的知识子查询是从最内层开始执行的由内而外因此上述语句的子查询执行之后sql 展开成下面的语句
```sql
-- 子查询展开后的结果
SELECT product_name, sale_price
FROM product
WHERE product_id IN ('0003', '0004', '0006', '0007');
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| 运动T恤      |       4000 |
| 菜刀         |       3000 |
| 叉子         |        500 |
| 擦菜板       |        880 |
+--------------+------------+
4 rows in set (0.00 sec)
```
可以看到,子查询转换之后变为 in 谓词用法,你理解了吗?
或者,你会疑惑既然 in 谓词也能实现,那为什么还要使用子查询呢?这里给出两点原因:
①:实际生活中,某个门店的在售商品是不断变化的,使用 in 谓词就需要经常更新 sql 语句,降低了效率,提高了维护成本;
②:实际上,某个门店的在售商品可能有成百上千个,手工维护在售商品编号真是个大工程。
使用子查询即可保持 sql 语句不变,极大提高了程序的可维护性,这是系统开发中需要重点考虑的内容。
* NOT IN和子查询
NOT IN 同样支持子查询作为参数,用法和 in 完全一样。
```sql
-- NOT IN 使用子查询作为参数,取出未在大阪门店销售的商品的销售单价
SELECT product_name, sale_price
FROM product
WHERE product_id NOT IN (SELECT product_id
FROM shopproduct
WHERE shop_id = '000A');
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| 菜刀         |       3000 |
| 高压锅       |       6800 |
| 叉子         |        500 |
| 擦菜板       |        880 |
| 圆珠笔       |        100 |
+--------------+------------+
5 rows in set (0.00 sec)
```
##
## 3.4.7 EXIST 谓词
EXIST 谓词的用法理解起来有些难度。
① EXIST 的使用方法与之前的都不相同
② 语法理解起来比较困难
③ 实际上即使不使用 EXIST基本上也都可以使用 IN或者 NOT IN来代替
这么说的话,还有学习 EXIST 谓词的必要吗?答案是肯定的,因为一旦能够熟练使用 EXIST 谓词,就能体会到它极大的便利性。
不过,你不用过于担心,本课程介绍一些基本用法,日后学习时可以多多留意 EXIST 谓词的用法,以期能够在达到 SQL 中级水平时掌握此用法。
* EXIST谓词的使用方法
谓词的作用就是 **“判断是否存在满足某种条件的记录”**。
如果存在这样的记录就返回真TRUE如果不存在就返回假FALSE
EXIST存在谓词的主语是“记录”。
我们继续以 IN和子查询 中的示例,使用 EXIST 选取出大阪门店在售商品的销售单价。
```sql
SELECT product_name, sale_price
FROM product AS p
WHERE EXISTS (SELECT *
FROM shopproduct AS sp
WHERE sp.shop_id = '000C'
AND sp.product_id = p.product_id);
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| 运动T恤      |       4000 |
| 菜刀         |       3000 |
| 叉子         |        500 |
| 擦菜板       |        880 |
+--------------+------------+
4 rows in set (0.00 sec)
```
* EXIST的参数
之前我们学过的谓词,基本上都是像“列 LIKE 字符串”或者“ 列 BETWEEN 值 1 AND 值 2”这样需要指定 2 个以上的参数,而 EXIST 的左侧并没有任何参数。因为 EXIST 是只有 1 个参数的谓词。 所以EXIST 只需要在右侧书写 1 个参数,该参数通常都会是一个子查询。
```sql
(SELECT *
FROM shopproduct AS sp
WHERE sp.shop_id = '000C'
AND sp.product_id = p.product_id)  
```
上面这样的子查询就是唯一的参数。确切地说由于通过条件“SP.product_id = P.product_id”将 product 表和 shopproduct表进行了联接因此作为参数的是关联子查询。 EXIST 通常会使用关联子查询作为参数。
* 子查询中的SELECT *
由于 EXIST 只关心记录是否存在,因此返回哪些列都没有关系。 EXIST 只会判断是否存在满足子查询中 WHERE 子句指定的条件“商店编号shop_id为 '000C'商品product表和商店
商品shopproduct表中商品编号product_id相同”的记录只有存在这样的记录时才返回真TRUE
因此,使用下面的查询语句,查询结果也不会发生变化。
```sql
SELECT product_name, sale_price
FROM product AS p
WHERE EXISTS (SELECT 1 -- 这里可以书写适当的常数
FROM shopproduct AS sp
WHERE sp.shop_id = '000C'
AND sp.product_id = p.product_id);
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| 运动T恤      |       4000 |
| 菜刀         |       3000 |
| 叉子         |        500 |
| 擦菜板       |        880 |
+--------------+------------+
4 rows in set (0.00 sec)
```
>大家可以把在 EXIST 的子查询中书写 SELECT * 当作 SQL 的一种习惯。
* 使用NOT EXIST替换NOT IN
就像 EXIST 可以用来替换 IN 一样, NOT IN 也可以用NOT EXIST来替换。
下面的代码示例取出,不在大阪门店销售的商品的销售单价。
```sql
SELECT product_name, sale_price
FROM product AS p
WHERE NOT EXISTS (SELECT *
FROM shopproduct AS sp
WHERE sp.shop_id = '000A'
AND sp.product_id = p.product_id);
+--------------+------------+
| product_name | sale_price |
+--------------+------------+
| 菜刀         |       3000 |
| 高压锅       |       6800 |
| 叉子         |        500 |
| 擦菜板       |        880 |
| 圆珠笔       |        100 |
+--------------+------------+
5 rows in set (0.00 sec)
```
NOT EXIST 与 EXIST 相反当“不存在”满足子查询中指定条件的记录时返回真TRUE
#
# 3.5 CASE 表达式
## 3.5.1 什么是 CASE 表达式?
CASE 表达式是函数的一种。是 SQL 中数一数二的重要功能,有必要好好学习一下。
CASE 表达式是在区分情况时使用的,这种情况的区分在编程中通常称为(条件)分支。
CASE表达式的语法分为简单CASE表达式和搜索CASE表达式两种。由于搜索CASE表达式包含简单CASE表达式的全部功能。本课程将重点介绍搜索CASE表达式。
语法:
```plain
CASE WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
WHEN <求值表达式> THEN <表达式>
.
.
.
ELSE <表达式>
END  
```
上述语句执行时,依次判断 when 表达式是否为真值,是则执行 THEN 后的语句,如果所有的 when 表达式均为假,则执行 ELSE 后的语句。
无论多么庞大的 CASE 表达式,最后也只会返回一个值。
##
## 3.5.2 CASE表达式的使用方法
假设现在 要实现如下结果:
```plain
A :衣服
B :办公用品
C :厨房用具  
```
因为表中的记录并不包含“A ”或者“B ”这样的字符串,所以需要在 SQL 中进行添加。并将“A ”“B ”“C ”与记录结合起来。
* **应用场景1根据不同分支得到不同列值**
```sql
SELECT  product_name,
CASE WHEN product_type = '衣服' THEN CONCAT('A ',product_type)
WHEN product_type = '办公用品'  THEN CONCAT('B ',product_type)
WHEN product_type = '厨房用具'  THEN CONCAT('C ',product_type)
ELSE NULL
END AS abc_product_type
FROM product;
+--------------+------------------+
| product_name | abc_product_type |
+--------------+------------------+
| T恤          | A 衣服        |
| 打孔器       | B 办公用品    |
| 运动T恤      | A 衣服        |
| 菜刀         | C 厨房用具    |
| 高压锅       | C 厨房用具    |
| 叉子         | C 厨房用具    |
| 擦菜板       | C 厨房用具    |
| 圆珠笔       | B 办公用品    |
+--------------+------------------+
8 rows in set (0.00 sec)
```
ELSE 子句也可以省略不写,这时会被默认为 ELSE NULL。但为了防止有人漏读还是希望大家能够显示地写出 ELSE 子句。
此外, CASE 表达式最后的“END”是不能省略的请大家特别注意不要遗漏。忘记书写 END 会发生语法错误,这也是初学时最容易犯的错误。
* **应用场景2实现列方向上的聚合**
通常我们使用如下代码实现行的方向上不同种类的聚合(这里是 sum
```sql
SELECT product_type,
SUM(sale_price) AS sum_price
FROM product
GROUP BY product_type;  
+--------------+-----------+
| product_type | sum_price |
+--------------+-----------+
| 衣服         |      5000 |
| 办公用品     |       600 |
| 厨房用具     |     11180 |
+--------------+-----------+
3 rows in set (0.00 sec)
```
假如要在列的方向上展示不同种类额聚合值,该如何写呢?
```plain
sum_price_clothes | sum_price_kitchen | sum_price_office
------------------+-------------------+-----------------
5000 | 11180 | 600  
```
聚合函数 + CASE WHEN 表达式即可实现该效果
```sql
-- 对按照商品种类计算出的销售单价合计值进行行列转换
SELECT SUM(CASE WHEN product_type = '衣服' THEN sale_price ELSE 0 END) AS sum_price_clothes,
SUM(CASE WHEN product_type = '厨房用具' THEN sale_price ELSE 0 END) AS sum_price_kitchen,
SUM(CASE WHEN product_type = '办公用品' THEN sale_price ELSE 0 END) AS sum_price_office
FROM product;
+-------------------+-------------------+------------------+
| sum_price_clothes | sum_price_kitchen | sum_price_office |
+-------------------+-------------------+------------------+
|              5000 |             11180 |              600 |
+-------------------+-------------------+------------------+
1 row in set (0.00 sec)
```
* **扩展内容应用场景3实现行转列**
假设有如下图表的结构
![图片](https://github.com/datawhalechina/team-learning-sql/blob/main/img/ch03/ch03.11casewhen1.png)
计划得到如下的图表结构
![图片](https://github.com/datawhalechina/team-learning-sql/blob/main/img/ch03/ch03.12casewhen2.png)
聚合函数 + CASE WHEN 表达式即可实现该转换
```sql
-- CASE WHEN 实现数字列 score 行转列
SELECT name,
SUM(CASE WHEN subject = '语文' THEN score ELSE null END) as chinese,
SUM(CASE WHEN subject = '数学' THEN score ELSE null END) as math,
SUM(CASE WHEN subject = '外语' THEN score ELSE null END) as english
FROM score
GROUP BY name;
+------+---------+------+---------+
| name | chinese | math | english |
+------+---------+------+---------+
| 张三 | 93 | 88 | 91 |
| 李四 | 87 | 90 | 77 |
+------+---------+------+---------+
2 rows in set (0.00 sec)
```
上述代码实现了数字列 score 的行转列,也可以实现文本列 subject 的行转列
```sql
-- CASE WHEN 实现文本列 subject 行转列
SELECT name,
MAX(CASE WHEN subject = '语文' THEN subject ELSE null END) as chinese,
MAX(CASE WHEN subject = '数学' THEN subject ELSE null END) as math,
MIN(CASE WHEN subject = '外语' THEN subject ELSE null END) as english
FROM score
GROUP BY name;
+------+---------+------+---------+
| name | chinese | math | english |
+------+---------+------+---------+
| 张三 | 语文 | 数学 | 外语 |
| 李四 | 语文 | 数学 | 外语 |
+------+---------+------+---------+
2 rows in set (0.00 sec
```
总结:
* 当待转换列为数字时,可以使用`SUM AVG MAX MIN`等聚合函数;
* 当待转换列为文本时,可以使用`MAX MIN`等聚合函数
#
# 练习题-第二部分
## 3.5 判断题
运算或者函数中含有 NULL 时结果是否都会变为NULL
## 3.6
对本章中使用的 `product`(商品)表执行如下 2 条 `SELECT` 语句,能够得到什么样的结果呢?
```sql
SELECT product_name, purchase_price
FROM product
WHERE purchase_price NOT IN (500, 2800, 5000);
```
```sql
SELECT product_name, purchase_price
FROM product
WHERE purchase_price NOT IN (500, 2800, 5000, NULL);
```
## 3.7
按照销售单价( `sale_price` )对练习 3.6 中的 `product`(商品)表中的商品进行如下分类。
* 低档商品销售单价在1000日元以下T恤衫、办公用品、叉子、擦菜板、 圆珠笔)
* 中档商品销售单价在1001日元以上3000日元以下菜刀
* 高档商品销售单价在3001日元以上运动T恤、高压锅
请编写出统计上述商品种类中所包含的商品数量的 SELECT 语句,结果如下所示。
执行结果
```sql
low_price | mid_price | high_price
----------+-----------+------------
5 | 1 | 2
```