SQL笔记(精简版)

文章目录

    • 数据库结构图
    • 1. 检索数据
      • 1.1 选择数据库
      • 1.2 选择单列
      • 1.3 选择多列
      • 1.4 选择所有列
      • 1.5 检索不同的值
      • 1.6 限制结果
      • 1.7 注释
      • 第一章练习题
    • 2. 排序检索数据
      • 2.1 排序数据
      • 2.2 按多个列排序
      • 2.3 按排列位置排序
      • 2.4 指定排序方向
      • 第二章练习题
    • 3. 过滤数据
      • 3.1 where子句
        • 3.1.1 检查单个值
        • 3.1.2 不匹配检查
        • 3.1.3 范围值检查
        • 3.1.4 空值检查
      • 第三章练习题
    • 4. 高级数据过滤
      • 4.1 组合where子句
        • 4.1.1 and操作符
        • 4.1.2 OR操作符
        • 4.1.3 求值顺序
      • 4.2 in操作符
      • 4.3 not操作符
      • 第四章练习题
    • 5. 用通配符进行过滤
      • 5.1 like操作符
        • 5.1.1 百分号(%)通配符
        • 5.1.2 下划线(_)通配符
        • 5.1.3 方括号([ ])通配符
      • 第五章练习题
    • 6. 计算字段
      • 6.1 算术字段
      • 6.2 拼接字段
      • 第六章练习题
    • 7. 使用函数处理数据
      • 7.1 文本处理函数
        • 7.1.1 left()函数
        • 7.1.2 lenth()函数
        • 7.1.3 lower()函数
        • 7.1.4 ltrim()函数
        • 7.1.5 right()函数
        • 7.1.6 rtrim()函数
        • 7.1.7 substr()函数
        • 7.1.8 soundex()函数
        • 7.1.9 upper()函数
      • 7.2 日期处理函数
      • 7.3 数值处理函数
      • 第七章练习题
    • 8. 汇总数据
      • 8.1 聚集函数
        • 8.1.1 avg()函数
        • 8.1.2 count()函数
        • 8.1.3 max()函数
        • 8.1.4 min()函数
        • 8.1.5 sum()函数
      • 8.2 组合聚集函数
      • 第八章练习题
    • 9. 分组数据
      • 9.1 创建分组
      • 9.2 过滤分组
      • 9.3 分组和排序
      • 第九章习题
    • 10. 使用子查询
      • 10.1 利用子查询进行过滤
      • 10.2 作为计算字段使用子查询
      • 第十章练习题
    • 11. 联结表
      • 11.1 创建联结
      • 11.2 内联结
      • 11.3 笛卡尔积
      • 11.4 联结多个表
    • 数据源

数据库结构图

sql5th
customers
orderitems
orders
vendors

表1:customers

customers

表2:orderitems

SQL笔记(精简版)_第1张图片

表3:orders

SQL笔记(精简版)_第2张图片

表4:vendors
SQL笔记(精简版)_第3张图片

1. 检索数据

1.1 选择数据库

USE sql5th;

1.2 选择单列

select prod_name from Products;
+---------------------+
| prod_name           |
+---------------------+
| Fish bean bag toy   |
| Bird bean bag toy   |
| Rabbit bean bag toy |
| 8 inch teddy bear   |
| 12 inch teddy bear  |
| 18 inch teddy bear  |
| Raggedy Ann         |
| King doll           |
| Queen doll          |
+---------------------+
9 rows in set
Time: 0.010s

1.3 选择多列

select prod_id, prod_name, prod_price from Products;
+---------+---------------------+------------+
| prod_id | prod_name           | prod_price |
+---------+---------------------+------------+
| BNBG01  | Fish bean bag toy   | 3.49       |
| BNBG02  | Bird bean bag toy   | 3.49       |
| BNBG03  | Rabbit bean bag toy | 3.49       |
| BR01    | 8 inch teddy bear   | 5.99       |
| BR02    | 12 inch teddy bear  | 8.99       |
| BR03    | 18 inch teddy bear  | 11.99      |
| RGAN01  | Raggedy Ann         | 4.99       |
| RYL01   | King doll           | 9.49       |
| RYL02   | Queen doll          | 9.49       |
+---------+---------------------+------------+
9 rows in set
Time: 0.006s

1.4 选择所有列

select * from Products;

1.5 检索不同的值

由下图可以看出产品供应商总共由3个,在我们查询的6个结果中含有重复的值。

select vend_id from products;
+---------+
| vend_id |
+---------+
| BRS01   |
| BRS01   |
| BRS01   |
| DLL01   |
| DLL01   |
| DLL01   |
| DLL01   |
| FNG01   |
| FNG01   |
+---------+
9 rows in set
Time: 0.006s

如果我们只想查询总共有多少供应商,我们应该怎么来写查询语句呢?

select distinct vend_id from Products;
+---------+
| vend_id |
+---------+
| BRS01   |
| DLL01   |
| FNG01   |
+---------+
3 rows in set
Time: 0.006s
select distinct vend_id, prod_price from Products;

从下图查询结果可以看出,当两列共同筛选唯一值时,只要每行数据都是唯一时,即可被筛选出来。

+---------+------------+
| vend_id | prod_price |
+---------+------------+
| DLL01   | 3.49       |
| BRS01   | 5.99       |
| BRS01   | 8.99       |
| BRS01   | 11.99      |
| DLL01   | 4.99       |
| FNG01   | 9.49       |
+---------+------------+
6 rows in set
Time: 0.006s
select vend_id, prod_price from Products;
+---------+------------+
| vend_id | prod_price |
+---------+------------+
| DLL01   | 3.49       |
| DLL01   | 3.49       |
| DLL01   | 3.49       |
| BRS01   | 5.99       |
| BRS01   | 8.99       |
| BRS01   | 11.99      |
| DLL01   | 4.99       |
| FNG01   | 9.49       |
| FNG01   | 9.49       |
+---------+------------+
9 rows in set
Time: 0.006s

1.6 限制结果

select prod_name from Products limit 5;

返回1-5行数据

+---------------------+
| prod_name           |
+---------------------+
| Fish bean bag toy   |
| Bird bean bag toy   |
| Rabbit bean bag toy |
| 8 inch teddy bear   |
| 12 inch teddy bear  |
+---------------------+
5 rows in set
Time: 0.005s

返回5-10行数据

select prod_name from Products limit 5 offset 5;
+--------------------+
| prod_name          |
+--------------------+
| 18 inch teddy bear |
| Raggedy Ann        |
| King doll          |
| Queen doll         |
+--------------------+
4 rows in set
Time: 0.006s

1.7 注释

--单行注释
/*
多行注释
*/

第一章练习题

第一题

编写SQL语句,从Customers表中检索所有的ID(cust_id)。

select cust_id from Customers;
+------------+
| cust_id    |
+------------+
| 1000000001 |
| 1000000002 |
| 1000000003 |
| 1000000004 |
| 1000000005 |
+------------+
5 rows in set
Time: 0.006s

第二题

OrderItems表包含了所有已订购的产品(有些已被订购多次)。编写SQL语句,检索并列出已订购产品(prod_id)的清单(不用列每个订单,只列出不同产品的清单)。提示:最终应该显示7行。

select distinct prod_id from OrderItems;
+---------+
| prod_id |
+---------+
| BNBG01  |
| BNBG02  |
| BNBG03  |
| BR01    |
| BR02    |
| BR03    |
| RGAN01  |
+---------+
7 rows in set
Time: 0.006s

第三题

编写SQL语句,检索Customers表中所有的列,再编写另外的SELECT语句,仅检索顾客的ID。使用注释,注释掉一条SELECT语句,以便运行另一条SELECT语句。(当然,要测试这两个语句。)

select * from Customers;
select cust_id from Customers;
+------------+
| cust_id    |
+------------+
| 1000000001 |
| 1000000002 |
| 1000000003 |
| 1000000004 |
| 1000000005 |
+------------+
5 rows in set
Time: 0.005s

2. 排序检索数据

2.1 排序数据

select prod_name from Products order by prod_name;

对prod_name列以字母顺序排序数据的ORDER BY子句外,这条语句与前面的语句相同。

+---------------------+
| prod_name           |
+---------------------+
| 12 inch teddy bear  |
| 18 inch teddy bear  |
| 8 inch teddy bear   |
| Bird bean bag toy   |
| Fish bean bag toy   |
| King doll           |
| Queen doll          |
| Rabbit bean bag toy |
| Raggedy Ann         |
+---------------------+
9 rows in set
Time: 0.006s

2.2 按多个列排序

select prod_id, prod_price, prod_name from Products order by prod_price,prod_name;

prod_price为第一排列顺序,prod_name为第二排列顺序。

+---------+------------+---------------------+
| prod_id | prod_price | prod_name           |
+---------+------------+---------------------+
| BNBG02  | 3.49       | Bird bean bag toy   |
| BNBG01  | 3.49       | Fish bean bag toy   |
| BNBG03  | 3.49       | Rabbit bean bag toy |
| RGAN01  | 4.99       | Raggedy Ann         |
| BR01    | 5.99       | 8 inch teddy bear   |
| BR02    | 8.99       | 12 inch teddy bear  |
| RYL01   | 9.49       | King doll           |
| RYL02   | 9.49       | Queen doll          |
| BR03    | 11.99      | 18 inch teddy bear  |
+---------+------------+---------------------+
9 rows in set
Time: 0.006s

2.3 按排列位置排序

select prod_id, prod_price, prod_name from Products order by 2,3;

ORDER BY 2表示按SELECT清单中的第二个列prod_price进行排序。ORDER BY 2, 3表示先按prod_price,再按prod_name进行排序。

+---------+------------+---------------------+
| prod_id | prod_price | prod_name           |
+---------+------------+---------------------+
| BNBG02  | 3.49       | Bird bean bag toy   |
| BNBG01  | 3.49       | Fish bean bag toy   |
| BNBG03  | 3.49       | Rabbit bean bag toy |
| RGAN01  | 4.99       | Raggedy Ann         |
| BR01    | 5.99       | 8 inch teddy bear   |
| BR02    | 8.99       | 12 inch teddy bear  |
| RYL01   | 9.49       | King doll           |
| RYL02   | 9.49       | Queen doll          |
| BR03    | 11.99      | 18 inch teddy bear  |
+---------+------------+---------------------+
9 rows in set
Time: 0.005s

2.4 指定排序方向

select prod_id, prod_price, prod_name from Products order by prod_price desc;

按照价格降序排列

+---------+------------+---------------------+
| prod_id | prod_price | prod_name           |
+---------+------------+---------------------+
| BR03    | 11.99      | 18 inch teddy bear  |
| RYL01   | 9.49       | King doll           |
| RYL02   | 9.49       | Queen doll          |
| BR02    | 8.99       | 12 inch teddy bear  |
| BR01    | 5.99       | 8 inch teddy bear   |
| RGAN01  | 4.99       | Raggedy Ann         |
| BNBG01  | 3.49       | Fish bean bag toy   |
| BNBG02  | 3.49       | Bird bean bag toy   |
| BNBG03  | 3.49       | Rabbit bean bag toy |
+---------+------------+---------------------+
9 rows in set
Time: 0.005s
select prod_id, prod_price, prod_name from Products order by prod_price desc, prod_name;

按照价格降序排列,产品名称仍然按照标准的升序排列。

+---------+------------+---------------------+
| prod_id | prod_price | prod_name           |
+---------+------------+---------------------+
| BR03    | 11.99      | 18 inch teddy bear  |
| RYL01   | 9.49       | King doll           |
| RYL02   | 9.49       | Queen doll          |
| BR02    | 8.99       | 12 inch teddy bear  |
| BR01    | 5.99       | 8 inch teddy bear   |
| RGAN01  | 4.99       | Raggedy Ann         |
| BNBG02  | 3.49       | Bird bean bag toy   |
| BNBG01  | 3.49       | Fish bean bag toy   |
| BNBG03  | 3.49       | Rabbit bean bag toy |
+---------+------------+---------------------+
9 rows in set
Time: 0.006s

第二章练习题

第一题

编写SQL语句,从Customers中检索所有的顾客名称(cust_names),并按从Z到A的顺序显示结果。

select cust_name from Customers order by cust_name desc;
+---------------+
| cust_name     |
+---------------+
| Village Toys  |
| The Toy Store |
| Kids Place    |
| Fun4All       |
| Fun4All       |
+---------------+
5 rows in set
Time: 0.006s

第二题

编写SQL语句,从Orders表中检索顾客ID(cust_id)和订单号(order_num),并先按顾客ID对结果进行排序,再按订单日期倒序排列。

select cust_id, order_num from orders order by 1,2 desc;
-- 或者
select cust_id, order_num from orders order by cust_id, order_num desc;
+------------+-----------+
| cust_id    | order_num |
+------------+-----------+
| 1000000001 | 20009     |
| 1000000001 | 20005     |
| 1000000003 | 20006     |
| 1000000004 | 20007     |
| 1000000005 | 20008     |
+------------+-----------+
5 rows in set
Time: 0.005s

第三题

显然,我们的虚拟商店更喜欢出售比较贵的物品,而且这类物品有很多。编写SQL语句,显示OrderItems表中的数量和价格(item_price),并按数量由多到少、价格由高到低排序。

select quantity, item_price from OrderItems order by quantity desc;
+----------+------------+
| quantity | item_price |
+----------+------------+
| 250      | 2.49       |
| 250      | 2.49       |
| 250      | 2.49       |
| 100      | 5.49       |
| 100      | 10.99      |
| 100      | 2.99       |
| 100      | 2.99       |
| 100      | 2.99       |
| 50       | 11.49      |
| 50       | 4.49       |
| 20       | 5.99       |
| 10       | 8.99       |
| 10       | 11.99      |
| 10       | 3.49       |
| 10       | 3.49       |
| 10       | 3.49       |
| 5        | 4.99       |
| 5        | 11.99      |
+----------+------------+
18 rows in set
Time: 0.005s

第四题

下面的SQL语句有问题吗?(尝试在不运行的情况下指出。)

select vend_name from Vendors order vend_name desc;
-- 正确语句
-- select vend_name from Vendors order by vend_name desc;

3. 过滤数据

3.1 where子句

select prod_name, prod_price from Products where prod_price = 3.49;
+---------------------+------------+
| prod_name           | prod_price |
+---------------------+------------+
| Fish bean bag toy   | 3.49       |
| Bird bean bag toy   | 3.49       |
| Rabbit bean bag toy | 3.49       |
+---------------------+------------+
3 rows in set
Time: 0.005s
操作符 说明 操作符 说明
= 等于 > 大于
<> 不等于 >= 大于等于
!= 不等于 !> 不大于
< 小于 BETWEEN 在指定的两个值之间
<= 小于等于 IS NULL 为NULL值
!< 不小于

3.1.1 检查单个值

select prod_name, prod_price from Products where prod_price < 10;

查询价格小于10美元的产品

+---------------------+------------+
| prod_name           | prod_price |
+---------------------+------------+
| Fish bean bag toy   | 3.49       |
| Bird bean bag toy   | 3.49       |
| Rabbit bean bag toy | 3.49       |
| 8 inch teddy bear   | 5.99       |
| 12 inch teddy bear  | 8.99       |
| Raggedy Ann         | 4.99       |
| King doll           | 9.49       |
| Queen doll          | 9.49       |
+---------------------+------------+
8 rows in set
Time: 0.005s

3.1.2 不匹配检查

select vend_id, prod_name from Products where vend_id <> "DLL01";

列出所有不是供应商DLL01制造的产品。

+---------+--------------------+
| vend_id | prod_name          |
+---------+--------------------+
| BRS01   | 8 inch teddy bear  |
| BRS01   | 12 inch teddy bear |
| BRS01   | 18 inch teddy bear |
| FNG01   | King doll          |
| FNG01   | Queen doll         |
+---------+--------------------+
5 rows in set
Time: 0.006s

3.1.3 范围值检查

select prod_name, prod_price from Products where prod_price between 5 and 10;
+--------------------+------------+
| prod_name          | prod_price |
+--------------------+------------+
| 8 inch teddy bear  | 5.99       |
| 12 inch teddy bear | 8.99       |
| King doll          | 9.49       |
| Queen doll         | 9.49       |
+--------------------+------------+
4 rows in set
Time: 0.005s

3.1.4 空值检查

select cust_name from Customers where cust_email is null;
+---------------+
| cust_name     |
+---------------+
| Kids Place    |
| The Toy Store |
+---------------+
2 rows in set
Time: 0.006s

第三章练习题

第一题

编写SQL语句,从Products表中检索产品ID(prod_id)和产品名称(prod_name),只返回价格为9.49美元的产品。

select prod_id, prod_name from Products where prod_price = 9.49;
+---------+------------+
| prod_id | prod_name  |
+---------+------------+
| RYL01   | King doll  |
| RYL02   | Queen doll |
+---------+------------+
2 rows in set
Time: 0.006s

第二题

编写SQL语句,从Products表中检索产品ID(prod_id)和产品名称(prod_name),只返回价格为9美元或更高的产品。

select prod_id, prod_name from Products where prod_price >= 9;
+---------+--------------------+
| prod_id | prod_name          |
+---------+--------------------+
| BR03    | 18 inch teddy bear |
| RYL01   | King doll          |
| RYL02   | Queen doll         |
+---------+--------------------+
3 rows in set
Time: 0.006s

第三题

结合第3课和第4课编写SQL语句,从OrderItems表中检索出所有不同订单号(order_num),其中包含100个或更多的产品。

select distinct order_num from OrderItems where order_num >=100;
+-----------+
| order_num |
+-----------+
| 20005     |
| 20006     |
| 20007     |
| 20008     |
| 20009     |
+-----------+
5 rows in set
Time: 0.006s

第四题

编写SQL语句,返回Products表中所有价格在3美元到6美元之间的产品的名称(prod_name)和价格(prod_price),然后按价格对结果进行排序。(本题有多种解决方案,我们在下一课再讨论,不过你可以使用目前已学的知识来解决它。)

select prod_name, prod_price from Products where prod_price between 3 and 6 order by prod_price;
+---------------------+------------+
| prod_name           | prod_price |
+---------------------+------------+
| Fish bean bag toy   | 3.49       |
| Bird bean bag toy   | 3.49       |
| Rabbit bean bag toy | 3.49       |
| Raggedy Ann         | 4.99       |
| 8 inch teddy bear   | 5.99       |
+---------------------+------------+
5 rows in set
Time: 0.005s

4. 高级数据过滤

4.1 组合where子句

4.1.1 and操作符

多个条件进行过滤,用在WHERE子句中的关键字,用来指示检索满足所有给定条件的行。

select prod_id, prod_price, prod_name from Products where vend_id = "DLL01" and prod_price <= 4;
+---------+------------+---------------------+
| prod_id | prod_price | prod_name           |
+---------+------------+---------------------+
| BNBG01  | 3.49       | Fish bean bag toy   |
| BNBG02  | 3.49       | Bird bean bag toy   |
| BNBG03  | 3.49       | Rabbit bean bag toy |
+---------+------------+---------------------+
3 rows in set
Time: 0.006s

4.1.2 OR操作符

WHERE子句中使用的关键字,用来表示检索匹配任一给定条件的行。

select prod_id, prod_price, prod_name from Products where vend_id = "DLL01" or vend_id ="BRS01";
+---------+------------+---------------------+
| prod_id | prod_price | prod_name           |
+---------+------------+---------------------+
| BR01    | 5.99       | 8 inch teddy bear   |
| BR02    | 8.99       | 12 inch teddy bear  |
| BR03    | 11.99      | 18 inch teddy bear  |
| BNBG01  | 3.49       | Fish bean bag toy   |
| BNBG02  | 3.49       | Bird bean bag toy   |
| BNBG03  | 3.49       | Rabbit bean bag toy |
| RGAN01  | 4.99       | Raggedy Ann         |
+---------+------------+---------------------+
7 rows in set
Time: 0.006s

4.1.3 求值顺序

select prod_name, prod_price from Products where vend_id = "DLL01" or vend_id = "BRS01" and prod_price >= 10;
+---------------------+------------+
| prod_name           | prod_price |
+---------------------+------------+
| 18 inch teddy bear  | 11.99      |
| Fish bean bag toy   | 3.49       |
| Bird bean bag toy   | 3.49       |
| Rabbit bean bag toy | 3.49       |
| Raggedy Ann         | 4.99       |
+---------------------+------------+
5 rows in set
Time: 0.006s
select prod_name, prod_price from Products where (vend_id = "DLL01" or vend_id = "BRS01") and prod_price >= 10;
+--------------------+------------+
| prod_name          | prod_price |
+--------------------+------------+
| 18 inch teddy bear | 11.99      |
+--------------------+------------+
1 row in set
Time: 0.005s

计算机逻辑运算符优先级not > and > or

4.2 in操作符

select prod_name, prod_price from Products where vend_id in("DLL01","BRS01") order by prod_name;
-- 或者
select prod_name, prod_price from Products where vend_id = "DLL01" or vend_id = "BRS01" order by prod_name;
+---------------------+------------+
| prod_name           | prod_price |
+---------------------+------------+
| 12 inch teddy bear  | 8.99       |
| 18 inch teddy bear  | 11.99      |
| 8 inch teddy bear   | 5.99       |
| Bird bean bag toy   | 3.49       |
| Fish bean bag toy   | 3.49       |
| Rabbit bean bag toy | 3.49       |
| Raggedy Ann         | 4.99       |
+---------------------+------------+
7 rows in set
Time: 0.006s

4.3 not操作符

WHERE子句中用来否定其后条件的关键字。

select prod_name from Products where not vend_id = "DLL01" order by prod_name;
-- 或者
select prod_name from Products where vend_id <> "DLL01" order by prod_name;
+--------------------+
| prod_name          |
+--------------------+
| 12 inch teddy bear |
| 18 inch teddy bear |
| 8 inch teddy bear  |
| King doll          |
| Queen doll         |
+--------------------+
5 rows in set
Time: 0.006s

第四章练习题

第一题

编写SQL语句,从Vendors表中检索供应商名称(vend_name),仅返回加利福尼亚州的供应商(这需要按国家[USA]和州[CA]进行过滤,没准其他国家也存在一个加利福尼亚州)。提示:过滤器需要匹配字符串。

select vend_name from Vendors where vend_state = "CA" and vend_country = "USA";
+-----------------+
| vend_name       |
+-----------------+
| Doll House Inc. |
+-----------------+
1 row in set
Time: 0.006s

第二题

编写SQL语句,查找所有至少订购了总量100个的BR01、BR02或BR03的订单。你需要返回OrderItems表的订单号(order_num)、产品ID(prod_id)和数量,并按产品ID和数量进行过滤。提示:根据编写过滤器的方式,可能需要特别注意求值顺序。

select order_num, prod_id,quantity from OrderItems where quantity >= 100;
+-----------+---------+----------+
| order_num | prod_id | quantity |
+-----------+---------+----------+
| 20005     | BR01    | 100      |
| 20005     | BR03    | 100      |
| 20007     | BNBG01  | 100      |
| 20007     | BNBG02  | 100      |
| 20007     | BNBG03  | 100      |
| 20009     | BNBG01  | 250      |
| 20009     | BNBG02  | 250      |
| 20009     | BNBG03  | 250      |
+-----------+---------+----------+
8 rows in set
Time: 0.005s

第三题

现在,我们回顾上一课的挑战题。编写SQL语句,返回所有价格在3美元到6美元之间的产品的名称(prod_name)和价格(prod_price)。使用AND,然后按价格对结果进行排序。

select prod_name, prod_price from Products where prod_price between 3 and 6;
+---------------------+------------+
| prod_name           | prod_price |
+---------------------+------------+
| Fish bean bag toy   | 3.49       |
| Bird bean bag toy   | 3.49       |
| Rabbit bean bag toy | 3.49       |
| 8 inch teddy bear   | 5.99       |
| Raggedy Ann         | 4.99       |
+---------------------+------------+
5 rows in set
Time: 0.007s

第四题

下面的SQL语句有问题吗?(尝试在不运行的情况下指出。)

select vend_name from Vendors order by vend_name where vend_country = "USA" and vend_state = "CA";
-- 修改
select vend_name from Vendors where vend_country = "USA" and vend_state = "CA" order by vend_name;

5. 用通配符进行过滤

**通配符(wildcard)**用来匹配值的一部分的特殊字符。

**搜索模式(search pattern)**由字面值、通配符或两者组合构成的搜索条件。

5.1 like操作符

5.1.1 百分号(%)通配符

符号 作用
%str 匹配以str结尾的字符串
str% 匹配以str开头的字符串
%str% 匹配含有str的字符串

str区分大小写

select  prod_id, prod_name from Products where prod_name like "Fish%";
+---------+-------------------+
| prod_id | prod_name         |
+---------+-------------------+
| BNBG01  | Fish bean bag toy |
+---------+-------------------+
1 row in set
Time: 0.006s
select  prod_id, prod_name from Products where prod_name like "%bean bag%";
+---------+---------------------+
| prod_id | prod_name           |
+---------+---------------------+
| BNBG01  | Fish bean bag toy   |
| BNBG02  | Bird bean bag toy   |
| BNBG03  | Rabbit bean bag toy |
+---------+---------------------+
3 rows in set
Time: 0.005s
select  prod_id, prod_name from Products where prod_name like "F%y";
+---------+-------------------+
| prod_id | prod_name         |
+---------+-------------------+
| BNBG01  | Fish bean bag toy |
+---------+-------------------+
1 row in set
Time: 0.005s

如果某列文本字段有20个字符,而存储的文本为Fish beanbag toy(17个字符),则为填满该列需要在文本后附加3个空格。这样做一般对数据及其使用没有影响,但是可能对上述SQL语句有负面影响。子句WHERE prod_name LIKE 'F%y’只匹配以F开头、以y结尾的prod_name。如果值后面跟空格,则不是以y结尾,所以Fish beanbag toy就不会检索出来。简单的解决办法是给搜索模式再增加一个%号:'F%y%’还匹配y之后的字符(或空格)。通配符%不匹配NULL值。

5.1.2 下划线(_)通配符

下划线(_)的用途与%一样,但它只匹配单个字符,而不是多个字符。

 select  prod_id, prod_name from Products where prod_name like "__ inch teddy bear";
+---------+--------------------+
| prod_id | prod_name          |
+---------+--------------------+
| BR02    | 12 inch teddy bear |
| BR03    | 18 inch teddy bear |
+---------+--------------------+
2 rows in set
Time: 0.005s

5.1.3 方括号([ ])通配符

方括号([])通配符用来指定一个字符集,它必须匹配指定位置(通配符的位置)的一个字符,[^str]表示不含str的字符串。

支持 不支持
SQL Server MySQL,Oracle,DB2,SQLite

第五章练习题

第一题

编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中包含toy一词的产品。

select prod_name, prod_desc from Products where  prod_desc like "%toy%";
+---------------------+-----------------------------------------------------------------------+
| prod_name           | prod_desc                                                             |
+---------------------+-----------------------------------------------------------------------+
| Fish bean bag toy   | Fish bean bag toy, complete with bean bag worms with which to feed it |
| Bird bean bag toy   | Bird bean bag toy, eggs are not included                              |
| Rabbit bean bag toy | Rabbit bean bag toy, comes with bean bag carrots                      |
+---------------------+-----------------------------------------------------------------------+
3 rows in set
Time: 0.006s

第二题

反过来再来一次。编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中未出现toy一词的产品。这次,按产品名称对结果进行排序。

--演示数据库为MySQL,不支持`[]`通配符,故换另一种方式演示。
select prod_name, prod_desc from Products where  prod_desc not like "%toy%";
+--------------------+--------------------------------------------------+
| prod_name          | prod_desc                                        |
+--------------------+--------------------------------------------------+
| 8 inch teddy bear  | 8 inch teddy bear, comes with cap and jacket     |
| 12 inch teddy bear | 12 inch teddy bear, comes with cap and jacket    |
| 18 inch teddy bear | 18 inch teddy bear, comes with cap and jacket    |
| Raggedy Ann        | 18 inch Raggedy Ann doll                         |
| King doll          | 12 inch king doll with royal garments and crown  |
| Queen doll         | 12 inch queen doll with royal garments and crown |
+--------------------+--------------------------------------------------+
6 rows in set
Time: 0.005s

第三题

编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中同时出现toy和carrots的产品。有好几种方法可以执行此操作,但对于这个挑战题,请使用AND和两个LIKE比较。

select prod_name, prod_desc from Products where  prod_desc like "%toy%" and prod_desc like "%carrots%";
+---------------------+--------------------------------------------------+
| prod_name           | prod_desc                                        |
+---------------------+--------------------------------------------------+
| Rabbit bean bag toy | Rabbit bean bag toy, comes with bean bag carrots |
+---------------------+--------------------------------------------------+
1 row in set
Time: 0.006s

第四题

来个比较棘手的。我没有特别向你展示这个语法,而是想看看你根据目前已学的知识是否可以找到答案。编写SQL语句,从Products表中检索产品名称(prod_name)和描述(prod_desc),仅返回在描述中以先后顺序同时出现toy和carrots的产品。提示:只需要用带有三个%符号的LIKE即可。

select prod_name, prod_desc from Products where  prod_desc like "%toy%carrots%";
+---------------------+--------------------------------------------------+
| prod_name           | prod_desc                                        |
+---------------------+--------------------------------------------------+
| Rabbit bean bag toy | Rabbit bean bag toy, comes with bean bag carrots |
+---------------------+--------------------------------------------------+
1 row in set
Time: 0.005s

6. 计算字段

6.1 算术字段

检索订单号20008中的所有物品。

select prod_id, quantity, item_price from orderitems where order_num = 20008;
+---------+----------+------------+
| prod_id | quantity | item_price |
+---------+----------+------------+
| RGAN01  | 5        | 4.99       |
| BR03    | 5        | 11.99      |
| BNBG01  | 10       | 3.49       |
| BNBG02  | 10       | 3.49       |
| BNBG03  | 10       | 3.49       |
+---------+----------+------------+
5 rows in set
Time: 0.006s

汇总物品价格。

select prod_id, quantity, item_price, quantity * item_price as expanded_price from orderitems where order_num = 20008;
+---------+----------+------------+----------------+
| prod_id | quantity | item_price | expanded_price |
+---------+----------+------------+----------------+
| RGAN01  | 5        | 4.99       | 24.95          |
| BR03    | 5        | 11.99      | 59.95          |
| BNBG01  | 10       | 3.49       | 34.90          |
| BNBG02  | 10       | 3.49       | 34.90          |
| BNBG03  | 10       | 3.49       | 34.90          |
+---------+----------+------------+----------------+
5 rows in set
Time: 0.005

6.2 拼接字段

select concat(vend_name, "(",vend_country, ")") from vendors order by vend_name;
+------------------------------------------+
| concat(vend_name, "(",vend_country, ")") |
+------------------------------------------+
| Bear Emporium(USA)                       |
| Bears R Us(USA)                          |
| Doll House Inc.(USA)                     |
| Fun and Games(England)                   |
| Furball Inc.(USA)                        |
| Jouets et ours(France)                   |
+------------------------------------------+
6 rows in set
Time: 0.006s

第六章练习题

第一题

别名的常见用法是在检索出的结果中重命名表的列字段(为了符合特定的报表要求或客户需求)。编写SQL语句,从Vendors表中检索vend_id、vend_name、vend_address和vend_city,将vend_name重命名为vname,将vend_city重命名为vcity,将vend_address重命名为vaddress。按供应商名称对结果进行排序(可以使用原始名称或新的名称)。

select vend_id, vend_name as vname, vend_address as vaddress, vend_city as vcity from vendors order by vname;
+---------+-----------------+-----------------+------------+
| vend_id | vname           | vaddress        | vcity      |
+---------+-----------------+-----------------+------------+
| BRE02   | Bear Emporium   | 500 Park Street | Anytown    |
| BRS01   | Bears R Us      | 123 Main Street | Bear Town  |
| DLL01   | Doll House Inc. | 555 High Street | Dollsville |
| FNG01   | Fun and Games   | 42 Galaxy Road  | London     |
| FRB01   | Furball Inc.    | 1000 5th Avenue | New York   |
| JTS01   | Jouets et ours  | 1 Rue Amusement | Paris      |
+---------+-----------------+-----------------+------------+
6 rows in set
Time: 0.006s

第二题

我们的示例商店正在进行打折促销,所有产品均降价10%。编写SQL语句,从Products表中返回prod_id、prod_price和sale_price。sale_price是一个包含促销价格的计算字段。提示:可以乘以0.9,得到原价的90%(即10%的折扣)。

select prod_id, prod_price, prod_price * 0.9 as sale_price from products;
+---------+------------+------------+
| prod_id | prod_price | sale_price |
+---------+------------+------------+
| BNBG01  | 3.49       | 3.141      |
| BNBG02  | 3.49       | 3.141      |
| BNBG03  | 3.49       | 3.141      |
| BR01    | 5.99       | 5.391      |
| BR02    | 8.99       | 8.091      |
| BR03    | 11.99      | 10.791     |
| RGAN01  | 4.99       | 4.491      |
| RYL01   | 9.49       | 8.541      |
| RYL02   | 9.49       | 8.541      |
+---------+------------+------------+
9 rows in set
Time: 0.005s

7. 使用函数处理数据

7.1 文本处理函数

函数 说明
left() 返回字符串左边的字符串
length(),datalength(),len() 返回字符串的长度
lower() 将字符串转换为小写
ltrim() 去掉字符串左边的空格
right() 返回字符串右边的字符
rtrim() 去掉字符串右边的空格
substr(),substring() 提取字符串的组成部分
sounddex() 返回字符串的soundex值
upper() 将字符串转换为大写

7.1.1 left()函数

select left(vend_name,3) from vendors;
+-------------------+
| left(vend_name,3) |
+-------------------+
| Bea               |
| Bea               |
| Dol               |
| Fun               |
| Fur               |
| Jou               |
+-------------------+
6 rows in set
Time: 0.006s

7.1.2 lenth()函数

select length(vend_name) from vendors;
+-------------------+
| left(vend_name,3) |
+-------------------+
| Bea               |
| Bea               |
| Dol               |
| Fun               |
| Fur               |
| Jou               |
+-------------------+
6 rows in set
Time: 0.005s

7.1.3 lower()函数

select lower(vend_name) from vendors;
+------------------+
| lower(vend_name) |
+------------------+
| bear emporium    |
| bears r us       |
| doll house inc.  |
| fun and games    |
| furball inc.     |
| jouets et ours   |
+------------------+
6 rows in set
Time: 0.006s

7.1.4 ltrim()函数

select ltrim(vend_name) from vendors;
+------------------+
| ltrim(vend_name) |
+------------------+
| Bear Emporium    |
| Bears R Us       |
| Doll House Inc.  |
| Fun and Games    |
| Furball Inc.     |
| Jouets et ours   |
+------------------+
6 rows in set
Time: 0.005s

7.1.5 right()函数

select right(vend_name,3) from vendors;
+--------------------+
| right(vend_name,3) |
+--------------------+
| ium                |
|  Us                |
| nc.                |
| mes                |
| nc.                |
| urs                |
+--------------------+
6 rows in set
Time: 0.005s

7.1.6 rtrim()函数

select rtrim(vend_name) from vendors;
+------------------+
| rtrim(vend_name) |
+------------------+
| Bear Emporium    |
| Bears R Us       |
| Doll House Inc.  |
| Fun and Games    |
| Furball Inc.     |
| Jouets et ours   |
+------------------+
6 rows in set
Time: 0.005s

7.1.7 substr()函数

-- 提取字符串第三个字符(含)及之后的部分
select substr(vend_name,3) from vendors;
+---------------------+
| substr(vend_name,3) |
+---------------------+
| ar Emporium         |
| ars R Us            |
| ll House Inc.       |
| n and Games         |
| rball Inc.          |
| uets et ours        |
+---------------------+
6 rows in set
Time: 0.006s

7.1.8 soundex()函数

-- 查找发音相似的字符串
select cust_name, cust_contact from customers where soundex(cust_contact) = soundex("Michael Green");
+------------+----------------+
| cust_name  | cust_contact   |
+------------+----------------+
| Kids Place | Michelle Green |
+------------+----------------+
1 row in set
Time: 0.006s

7.1.9 upper()函数

select vend_name, upper(vend_name) as vend_name_name_upcase from vendors order by vend_name;
+-----------------+-----------------------+
| vend_name       | vend_name_name_upcase |
+-----------------+-----------------------+
| Bear Emporium   | BEAR EMPORIUM         |
| Bears R Us      | BEARS R US            |
| Doll House Inc. | DOLL HOUSE INC.       |
| Fun and Games   | FUN AND GAMES         |
| Furball Inc.    | FURBALL INC.          |
| Jouets et ours  | JOUETS ET OURS        |
+-----------------+-----------------------+
6 rows in set
Time: 0.006s

7.2 日期处理函数

select order_num from orders where year(order_date) = 2020;
+-----------+
| order_num |
+-----------+
| 20005     |
| 20006     |
| 20007     |
| 20008     |
| 20009     |
+-----------+
5 rows in set
Time: 0.006s

7.3 数值处理函数

函数 说明
abs() 返回一个数的绝对值
cos() 返回一个角度的余弦
exp() 返回一个数的指数值
pi() 返回圆周率 π \pi π的值
sin() 返回一个角度的正弦
sqrt() 返回一个数的平方根
tan() 返回一个角度的正切

第七章练习题

第一题

所有用户都需要登录名,默认登录名是其名称和所在城市的组合。编写SQL语句,返回顾客ID(cust_id)、顾客名称(customer_name)和登录名(user_login),其中登录名全部为大写字母,并由顾客联系人的前两个字符(cust_contact)和其所在城市的前三个字符(cust_city)组成。例如,我的登录名是BEOAK(Ben Forta,居住在Oak Park)。提示:需要使用函数、拼接和别名。

select cust_id, cust_name as customer_name, upper(concat(left(cust_contact,2),left(cust_city,3))) as user_login from customers;
+------------+---------------+------------+
| cust_id    | customer_name | user_login |
+------------+---------------+------------+
| 1000000001 | Village Toys  | JODET      |
| 1000000002 | Kids Place    | MICOL      |
| 1000000003 | Fun4All       | JIMUN      |
| 1000000004 | Fun4All       | DEPHO      |
| 1000000005 | The Toy Store | KICHI      |
+------------+---------------+------------+
5 rows in set
Time: 0.007s

第二题

编写SQL语句,返回2020年1月的所有订单的订单号(order_num)和订单日期(order_date),并按订单日期排序。你应该能够根据目前已学的知识来解决此问题,但也可以开卷查阅DBMS文档。

select order_num, order_date from orders where year(order_date) = 2020 and month(order_date) = 01;
+-----------+---------------------+
| order_num | order_date          |
+-----------+---------------------+
| 20006     | 2020-01-12 00:00:00 |
| 20007     | 2020-01-30 00:00:00 |
+-----------+---------------------+
2 rows in set
Time: 0.006s

8. 汇总数据

8.1 聚集函数

函数 说明
avg() 返回某列的平均值
count() 返回某列的行数
max() 返回某列的最大值
min() 返回某列的最小值
sum 返回某列值之和

8.1.1 avg()函数

-- avg()函数忽略null值
select avg(prod_price) as avg_price from products;
+-----------+
| avg_price |
+-----------+
| 6.823333  |
+-----------+
1 row in set
Time: 0.005s

8.1.2 count()函数

  • count(*)包含所有行。
  • count(colnm)忽略含有null
select count(*) as num_cust from customers;
+----------+
| num_cust |
+----------+
| 5        |
+----------+
1 row in set
Time: 0.009s
select count(cust_email) as num_cust from customers;
+----------+
| num_cust |
+----------+
| 3        |
+----------+
1 row in set
Time: 0.006s

8.1.3 max()函数

-- max()忽略null值
select max(prod_price) as max_price from products;
+-----------+
| max_price |
+-----------+
| 11.99     |
+-----------+
1 row in set
Time: 0.006s

8.1.4 min()函数

max()

8.1.5 sum()函数

 -- sum()忽略null值
select sum(quantity) as items_ordered from orderitems where order_num = 20005;
+---------------+
| items_ordered |
+---------------+
| 200           |
+---------------+
1 row in set
Time: 0.006s

8.2 组合聚集函数

select count(*) as num_items, min(prod_price) as price_min, max(prod_price) as price_max, avg(prod_price) as price_avg from products;
+-----------+-----------+-----------+-----------+
| num_items | price_min | price_max | price_avg |
+-----------+-----------+-----------+-----------+
| 9         | 3.49      | 11.99     | 6.823333  |
+-----------+-----------+-----------+-----------+
1 row in set
Time: 0.006s

第八章练习题

第一题

编写SQL语句,确定已售出产品的总数(使用OrderItems中的quantity列)。

select sum(quantity) from orderitems;
+---------------+
| sum(quantity) |
+---------------+
| 1430          |
+---------------+
1 row in set
Time: 0.006s

第二题

修改刚刚创建的语句,确定已售出产品项(prod_item)BR01的总数。

 select sum(order_item) from orderitems where prod_id = "BR01";
+-----------------+
| sum(order_item) |
+-----------------+
| 2               |
+-----------------+
1 row in set
Time: 0.006s

第三题

编写SQL语句,确定Products表中价格不超过10美元的最贵产品的价格(prod_price)。将计算所得的字段命名为max_price。

select max(prod_price) as max_price from products where prod_price <= 10;
+-----------+
| max_price |
+-----------+
| 9.49      |
+-----------+
1 row in set
Time: 0.006s

9. 分组数据

9.1 创建分组

select vend_id, count(*) as num_prods from products group by vend_id;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| BRS01   | 3         |
| DLL01   | 4         |
| FNG01   | 2         |
+---------+-----------+
3 rows in set
Time: 0.005s

9.2 过滤分组

说明:HAVING和WHERE的差别这里有另一种理解方法,WHERE在数据分组前进行过滤,HAVING在数据分组后进行过滤。这是一个重要的区别,WHERE排除的行不包括在分组中。这可能会改变计算值,从而影响HAVING子句中基于这些值过滤掉的分组。

select cust_id, count(*) as orders from orders group by cust_id having count(*) >= 2;
+------------+--------+
| cust_id    | orders |
+------------+--------+
| 1000000001 | 2      |
+------------+--------+
1 row in set
Time: 0.005s
select vend_id, count(*) as num_prods from products where prod_price >=4 group by vend_id having count(*) >= 2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| BRS01   | 3         |
| FNG01   | 2         |
+---------+-----------+
2 rows in set
Time: 0.007s
select vend_id, count(*) as num_prods from products where prod_price >= 4 group by vend_id having count(*) >= 2;
+---------+-----------+
| vend_id | num_prods |
+---------+-----------+
| BRS01   | 3         |
| FNG01   | 2         |
+---------+-----------+
2 rows in set
Time: 0.006s

9.3 分组和排序

select order_num, count(*) as items from orderitems group by order_num having count(*) >= 3 order by items, order_num;
+-----------+-------+
| order_num | items |
+-----------+-------+
| 20006     | 3     |
| 20009     | 3     |
| 20007     | 5     |
| 20008     | 5     |
+-----------+-------+
4 rows in set
Time: 0.006s

第九章习题

第一题

OrderItems表包含每个订单的每个产品。编写SQL语句,返回每个订单号(order_num)各有多少行数(order_lines),并按order_lines对结果进行排序。

select order_num, count(*) as order_lines from orderitems group by order_num order by order_lines;
+-----------+-------------+
| order_num | order_lines |
+-----------+-------------+
| 20005     | 2           |
| 20006     | 3           |
| 20009     | 3           |
| 20007     | 5           |
| 20008     | 5           |
+-----------+-------------+
5 rows in set
Time: 0.006s

第二题

编写SQL语句,返回名为cheapest_item的字段,该字段包含每个供应商成本最低的产品(使用Products表中的prod_price),然后从最低成本到最高成本对结果进行排序。

select min(prod_price) as cheapest_item from products group by vend_id;
+---------------+
| cheapest_item |
+---------------+
| 5.99          |
| 3.49          |
| 9.49          |
+---------------+
3 rows in set
Time: 0.006s

第三题

确定最佳顾客非常重要,请编写SQL语句,返回至少含100项的所有订单的订单号(OrderItems表中的order_num)。

select order_num, sum(quantity) as sum_quantity from orderitems group by order_num having sum_quantity >= 100 ;
+-----------+--------------+
| order_num | sum_quantity |
+-----------+--------------+
| 20005     | 200          |
| 20007     | 400          |
| 20009     | 750          |
+-----------+--------------+
3 rows in set
Time: 0.006s

第四题

确定最佳顾客的另一种方式是看他们花了多少钱。编写SQL语句,返回总价至少为1000的所有订单的订单号(OrderItems表中的order_num)。提示:需要计算总和(item_price乘以quantity)。按订单号对结果进行排序。

select order_num, sum(item_price * quantity) as total from orderitems group by order_num having total >= 1000 order by order_num;
+-----------+---------+
| order_num | total   |
+-----------+---------+
| 20005     | 1648.00 |
| 20007     | 1696.00 |
| 20009     | 1867.50 |
+-----------+---------+
3 rows in set
Time: 0.006s

第五题

下面的SQL语句有问题吗?(尝试在不运行的情况下指出。)

-- count(*)不能通过group by 进行分组
select order_num, count(*) as items from orderitems group by items having count(*) >= 3 order by items. order_num;

10. 使用子查询

10.1 利用子查询进行过滤

列出订购物品RGAN01的所有顾客。

  • 第一步检索包含物品RGAN01的所有订单的编号。
  • 第二步检索具有前一步骤列出的订单编号的所有顾客的ID。
  • 第三步检索前一步骤返回的所有顾客ID的顾客信息。
-- 第一步
select order_num from orderitems where prod_id = "RGAN01";
+-----------+
| order_num |
+-----------+
| 20007     |
| 20008     |
+-----------+
2 rows in set
Time: 0.006s
-- 第二步
select cust_id from orders where order_num in (20007,20008);
+------------+
| cust_id    |
+------------+
| 1000000004 |
| 1000000005 |
+------------+
2 rows in set
Time: 0.005s
-- 第三步
select cust_name, cust_contact from customers where cust_id in (1000000004,1000000005);
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set
Time: 0.006s

通过嵌套子查询将以上三条语句合并为一条。

-- 嵌套子查询
select cust_name, cust_contact from customers where cust_id in(
    select cust_id from orders where order_num in(
        select order_num from orderitems where prod_id = "RGAN01"
    ));
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set
Time: 0.006s

10.2 作为计算字段使用子查询

查询Customers表中每个顾客的订单总数。

  • 第一步从Customers表中检索顾客列表;
  • 第二步对于检索出的每个顾客,统计其在Orders表中的订单数目。
-- 第一步
select count(*) as orders from orders where cust_id = 1000000001;
+--------+
| orders |
+--------+
| 2      |
+--------+
1 row in set
Time: 0.006s
-- 第二步
select cust_name, cust_state, (
    select count(*) from orders where orders.cust_id = customers.cust_id
) as orders from customers order by cust_name;
+---------------+------------+--------+
| cust_name     | cust_state | orders |
+---------------+------------+--------+
| Fun4All       | IN         | 1      |
| Fun4All       | AZ         | 1      |
| Kids Place    | OH         | 0      |
| The Toy Store | IL         | 1      |
| Village Toys  | MI         | 2      |
+---------------+------------+--------+
5 rows in set
Time: 0.007s

第十章练习题

第一题

使用子查询,返回购买价格为10美元或以上产品的顾客列表。你需要使用OrderItems表查找匹配的订单号(order_num),然后使用Order表检索这些匹配订单的顾客ID(cust_id)。

select cust_name, cust_contact from customers where cust_id in (
    select cust_id from orders where orders.order_num in (
        select order_num from orderitems where item_price>=10));
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Village Toys  | John Smith         |
| Fun4All       | Jim Jones          |
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
4 rows in set
Time: 0.006s

第二题

你想知道订购BR01产品的日期。编写SQL语句,使用子查询来确定哪些订单(在OrderItems中)购买了prod_id为BR01的产品,然后从Orders表中返回每个产品对应的顾客ID(cust_id)和订单日期(order_date)。按订购日期对结果进行排序。

select cust_id, order_date from orders where order_num in (
    select order_num from orderitems where prod_id = "BR01"
) order by order_date;
+------------+---------------------+
| cust_id    | order_date          |
+------------+---------------------+
| 1000000003 | 2020-01-12 00:00:00 |
| 1000000001 | 2020-05-01 00:00:00 |
+------------+---------------------+
2 rows in set
Time: 0.006s

第三题

现在我们让它更具挑战性。在上一个挑战题,返回购买prod_id为BR01的产品的所有顾客的电子邮件(Customers表中的cust_email)。提示:这涉及SELECT语句,最内层的从OrderItems表返回order_num,中间的从Customers表返回cust_id。

select cust_id, cust_email from customers where cust_id in (
    select cust_id from orders where order_num in (
        select order_num from orderitems where prod_id = "BR01")) 
+------------+-----------------------+
| cust_id    | cust_email            |
+------------+-----------------------+
| 1000000001 | [email protected] |
| 1000000003 | [email protected]    |
+------------+-----------------------+
2 rows in set
Time: 0.006s

第四题

我们需要一个顾客ID列表,其中包含他们已订购的总金额。编写SQL语句,返回顾客ID(Orders表中的cust_id),并使用子查询返回total_ordered以便返回每个顾客的订单总数。将结果按金额从大到小排序。提示:你之前已经使用SUM()计算订单总数。

select cust_id, (
    select sum(item_price * quantity) from orderitems where orders.order_num = orderitems.order_num) as total_ordered 
    from orders order by total_ordered desc;
+------------+---------------+
| cust_id    | total_ordered |
+------------+---------------+
| 1000000001 | 1867.50       |
| 1000000004 | 1696.00       |
| 1000000001 | 1648.00       |
| 1000000003 | 329.60        |
| 1000000005 | 189.60        |
+------------+---------------+
5 rows in set
Time: 0.007s

第五题

再来。编写SQL语句,从Products表中检索所有的产品名称(prod_name),以及名为quant_sold的计算列,其中包含所售产品的总数(在OrderItems表上使用子查询和SUM(quantity)检索)

select prod_name, (
    select sum(quantity) from orderitems where orderitems.prod_id = products.prod_id
) as quant_sold from products;
+---------------------+------------+
| prod_name           | quant_sold |
+---------------------+------------+
| Fish bean bag toy   | 360        |
| Bird bean bag toy   | 360        |
| Rabbit bean bag toy | 360        |
| 8 inch teddy bear   | 120        |
| 12 inch teddy bear  | 10         |
| 18 inch teddy bear  | 165        |
| Raggedy Ann         | 55         |
| King doll           |      |
| Queen doll          |      |
+---------------------+------------+
9 rows in set
Time: 0.005s

11. 联结表

11.1 创建联结

select vend_name, prod_name, prod_price from vendors, products where vendors.vend_id = products.vend_id;
+-----------------+---------------------+------------+
| vend_name       | prod_name           | prod_price |
+-----------------+---------------------+------------+
| Doll House Inc. | Fish bean bag toy   | 3.49       |
| Doll House Inc. | Bird bean bag toy   | 3.49       |
| Doll House Inc. | Rabbit bean bag toy | 3.49       |
| Bears R Us      | 8 inch teddy bear   | 5.99       |
| Bears R Us      | 12 inch teddy bear  | 8.99       |
| Bears R Us      | 18 inch teddy bear  | 11.99      |
| Doll House Inc. | Raggedy Ann         | 4.99       |
| Fun and Games   | King doll           | 9.49       |
| Fun and Games   | Queen doll          | 9.49       |
+-----------------+---------------------+------------+
9 rows in set
Time: 0.006s

11.2 内联结

-- 查询结果同上
select vend_name, prod_name, prod_price from vendors inner join products on vendors.vend_id = products.vend_id;
+-----------------+---------------------+------------+
| vend_name       | prod_name           | prod_price |
+-----------------+---------------------+------------+
| Doll House Inc. | Fish bean bag toy   | 3.49       |
| Doll House Inc. | Bird bean bag toy   | 3.49       |
| Doll House Inc. | Rabbit bean bag toy | 3.49       |
| Bears R Us      | 8 inch teddy bear   | 5.99       |
| Bears R Us      | 12 inch teddy bear  | 8.99       |
| Bears R Us      | 18 inch teddy bear  | 11.99      |
| Doll House Inc. | Raggedy Ann         | 4.99       |
| Fun and Games   | King doll           | 9.49       |
| Fun and Games   | Queen doll          | 9.49       |
+-----------------+---------------------+------------+
9 rows in set
Time: 0.006s

11.3 笛卡尔积

笛卡儿积(cartesian product)由没有联结条件的表关系返回的结果为笛卡儿积。检索出的行的数目将是第一个表中的行数乘以第二个表中的行数。

11.4 联结多个表

select prod_name, vend_name, prod_price, quantity from orderitems, products, vendors where products.vend_id = vendors.vend_id and orderitems.prod_id = products.prod_id and order_num = 20007;
+---------------------+-----------------+------------+----------+
| prod_name           | vend_name       | prod_price | quantity |
+---------------------+-----------------+------------+----------+
| 18 inch teddy bear  | Bears R Us      | 11.99      | 50       |
| Fish bean bag toy   | Doll House Inc. | 3.49       | 100      |
| Bird bean bag toy   | Doll House Inc. | 3.49       | 100      |
| Rabbit bean bag toy | Doll House Inc. | 3.49       | 100      |
| Raggedy Ann         | Doll House Inc. | 4.99       | 50       |
+---------------------+-----------------+------------+----------+
5 rows in set
Time: 0.014s

下面我们通过联结表来解决10.1的问题。

select cust_name, cust_contact from customers, orders, orderitems where customers.cust_id = orders.cust_id and orderitems.order_num = orders.order_num and prod_id = "RGAN01";
+---------------+--------------------+
| cust_name     | cust_contact       |
+---------------+--------------------+
| Fun4All       | Denise L. Stephens |
| The Toy Store | Kim Howard         |
+---------------+--------------------+
2 rows in set
Time: 0.006s

数据源

-- Ceate
-- Sams Teach Yourself SQL in 10 Minutes, 5th Edition
-- http://forta.com/books/0135182794/
-- Example table creation scripts for MySQL & MariaDB


-- ----------------------
-- Create Customers table
-- ----------------------
CREATE TABLE Customers
(
  cust_id      char(10)  NOT NULL ,
  cust_name    char(50)  NOT NULL ,
  cust_address char(50)  NULL ,
  cust_city    char(50)  NULL ,
  cust_state   char(5)   NULL ,
  cust_zip     char(10)  NULL ,
  cust_country char(50)  NULL ,
  cust_contact char(50)  NULL ,
  cust_email   char(255) NULL 
);

-- -----------------------
-- Create OrderItems table
-- -----------------------
CREATE TABLE OrderItems
(
  order_num  int          NOT NULL ,
  order_item int          NOT NULL ,
  prod_id    char(10)     NOT NULL ,
  quantity   int          NOT NULL ,
  item_price decimal(8,2) NOT NULL 
);


-- -------------------
-- Create Orders table
-- -------------------
CREATE TABLE Orders
(
  order_num  int      NOT NULL ,
  order_date datetime NOT NULL ,
  cust_id    char(10) NOT NULL 
);

-- ---------------------
-- Create Products table
-- ---------------------
CREATE TABLE Products
(
  prod_id    char(10)      NOT NULL ,
  vend_id    char(10)      NOT NULL ,
  prod_name  char(255)     NOT NULL ,
  prod_price decimal(8,2)  NOT NULL ,
  prod_desc  text          NULL 
);

-- --------------------
-- Create Vendors table
-- --------------------
CREATE TABLE Vendors
(
  vend_id      char(10) NOT NULL ,
  vend_name    char(50) NOT NULL ,
  vend_address char(50) NULL ,
  vend_city    char(50) NULL ,
  vend_state   char(5)  NULL ,
  vend_zip     char(10) NULL ,
  vend_country char(50) NULL 
);


-- -------------------
-- Define primary keys
-- -------------------
ALTER TABLE Customers ADD PRIMARY KEY (cust_id);
ALTER TABLE OrderItems ADD PRIMARY KEY (order_num, order_item);
ALTER TABLE Orders ADD PRIMARY KEY (order_num);
ALTER TABLE Products ADD PRIMARY KEY (prod_id);
ALTER TABLE Vendors ADD PRIMARY KEY (vend_id);


-- -------------------
-- Define foreign keys
-- -------------------
ALTER TABLE OrderItems ADD CONSTRAINT FK_OrderItems_Orders FOREIGN KEY (order_num) REFERENCES Orders (order_num);
ALTER TABLE OrderItems ADD CONSTRAINT FK_OrderItems_Products FOREIGN KEY (prod_id) REFERENCES Products (prod_id);
ALTER TABLE Orders ADD CONSTRAINT FK_Orders_Customers FOREIGN KEY (cust_id) REFERENCES Customers (cust_id);
ALTER TABLE Products ADD CONSTRAINT FK_Products_Vendors FOREIGN KEY (vend_id) REFERENCES Vendors (vend_id);

--Populate
-- Sams Teach Yourself SQL in 10 Minutes, 5th Edition
-- http://forta.com/books/0135182794/
-- Example table population scripts for MySQL & MariaDB
-- ------------------------
-- Populate Customers table
-- ------------------------
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000001', 'Village Toys', '200 Maple Lane', 'Detroit', 'MI', '44444', 'USA', 'John Smith', '[email protected]');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES('1000000002', 'Kids Place', '333 South Lake Drive', 'Columbus', 'OH', '43333', 'USA', 'Michelle Green');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000003', 'Fun4All', '1 Sunny Place', 'Muncie', 'IN', '42222', 'USA', 'Jim Jones', '[email protected]');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact, cust_email)
VALUES('1000000004', 'Fun4All', '829 Riverside Drive', 'Phoenix', 'AZ', '88888', 'USA', 'Denise L. Stephens', '[email protected]');
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_contact)
VALUES('1000000005', 'The Toy Store', '4545 53rd Street', 'Chicago', 'IL', '54545', 'USA', 'Kim Howard');

-- ----------------------
-- Populate Vendors table
-- ----------------------
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
VALUES('BRS01','Bears R Us','123 Main Street','Bear Town','MI','44444', 'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
VALUES('BRE02','Bear Emporium','500 Park Street','Anytown','OH','44333', 'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
VALUES('DLL01','Doll House Inc.','555 High Street','Dollsville','CA','99999', 'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
VALUES('FRB01','Furball Inc.','1000 5th Avenue','New York','NY','11111', 'USA');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
VALUES('FNG01','Fun and Games','42 Galaxy Road','London', NULL,'N16 6PS', 'England');
INSERT INTO Vendors(vend_id, vend_name, vend_address, vend_city, vend_state, vend_zip, vend_country)
VALUES('JTS01','Jouets et ours','1 Rue Amusement','Paris', NULL,'45678', 'France');

-- -----------------------
-- Populate Products table
-- -----------------------
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR01', 'BRS01', '8 inch teddy bear', 5.99, '8 inch teddy bear, comes with cap and jacket');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR02', 'BRS01', '12 inch teddy bear', 8.99, '12 inch teddy bear, comes with cap and jacket');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BR03', 'BRS01', '18 inch teddy bear', 11.99, '18 inch teddy bear, comes with cap and jacket');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG01', 'DLL01', 'Fish bean bag toy', 3.49, 'Fish bean bag toy, complete with bean bag worms with which to feed it');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG02', 'DLL01', 'Bird bean bag toy', 3.49, 'Bird bean bag toy, eggs are not included');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('BNBG03', 'DLL01', 'Rabbit bean bag toy', 3.49, 'Rabbit bean bag toy, comes with bean bag carrots');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RGAN01', 'DLL01', 'Raggedy Ann', 4.99, '18 inch Raggedy Ann doll');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RYL01', 'FNG01', 'King doll', 9.49, '12 inch king doll with royal garments and crown');
INSERT INTO Products(prod_id, vend_id, prod_name, prod_price, prod_desc)
VALUES('RYL02', 'FNG01', 'Queen doll', 9.49, '12 inch queen doll with royal garments and crown');

-- ---------------------
-- Populate Orders table
-- ---------------------
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20005, '2020-05-01', '1000000001');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20006, '2020-01-12', '1000000003');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20007, '2020-01-30', '1000000004');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20008, '2020-02-03', '1000000005');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20009, '2020-02-08', '1000000001');

-- -------------------------
-- Populate OrderItems table
-- -------------------------
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20005, 1, 'BR01', 100, 5.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20005, 2, 'BR03', 100, 10.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20006, 1, 'BR01', 20, 5.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20006, 2, 'BR02', 10, 8.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20006, 3, 'BR03', 10, 11.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20007, 1, 'BR03', 50, 11.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20007, 2, 'BNBG01', 100, 2.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20007, 3, 'BNBG02', 100, 2.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20007, 4, 'BNBG03', 100, 2.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20007, 5, 'RGAN01', 50, 4.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20008, 1, 'RGAN01', 5, 4.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20008, 2, 'BR03', 5, 11.99);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20008, 3, 'BNBG01', 10, 3.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20008, 4, 'BNBG02', 10, 3.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20008, 5, 'BNBG03', 10, 3.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20009, 1, 'BNBG01', 250, 2.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20009, 2, 'BNBG02', 250, 2.49);
INSERT INTO OrderItems(order_num, order_item, prod_id, quantity, item_price)
VALUES(20009, 3, 'BNBG03', 250, 2.49);

你可能感兴趣的:(笔记,mysql)