数据库习题

每一章的习题都在这里。

1

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

SELECT cust_id
FROM Customers;

2

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

 SELECT DISTINCT Prod_id
 FROM OrderItems;

3

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

 /*SELECT * 
 FROM Customers;*/
 SELECT cust_id
 FROM Customers;

4

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

 SELECT cust_names
 FROM Customers
 ORDER BY cust_name DESC;

5

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

 SELECT cust_id, order_num
 FROM Orders
 ORDER BY cust_id, order_date DESC;

6

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

 SELECT quantity, item_price
 FROM OrderItems
 ORDER BY quantity DESC , item_price DESC;

7

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

 SELECT vend_name,
 FROM Vendors
 ORDER vend_name DESC;

少了一个BY

8

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

 SELECT prod_id, prod_name
 FROM Products
 WHERE prod_price = 9.49;

9

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

 SELECT prod_id, prod_name
 FROM Products
 WHERE prod_price >= 9;

10

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

 SELECT DISTINCT order_num
 FROM OrderItems
 WHERE quantity >=100;

11

编写 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;

12

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

 SELECT vend_name
 FROM Vendors
 WHERE vend_country = 'USA' AND vend_state = 'CA';

13

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

 SELECT order_num, prod_id
 FROM OrderItems
 WHERE quantity >= 100 AND prod_id = 'BR01' OR prod_id = 'BR02' OR prod_id = 'BR03';

14

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

 SELECT prod_name, prod_price
 FROM Products
 WHERE prod_price = 3 AND prod_price = 6
 ORDER BY prod_price;

15

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

 SELECT vend_name
 FROM Vendors
 ORDER BY vend_name
 WHERE vend_country = 'USA' AND vend_state = 'CA';

ORDER BY子句应该写在最后面。

16

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

 SELECT prod_name, prod_desc
 FROM Products
 WHERE prod_desc LIKE '%toy%';

17

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

 SELECT prod_name, prod_desc
 FROM Products
 WHERE prod_desc NOT LIKE '%toy%';

18

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

 SELECT prod_name, prod_desc
 FROM Products
 WHERE Products NOT LIKE '%toy%' AND Products NOT LIKE '%carrots%';

19

编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回在描述中以先后顺序同时出现 toy 和 carrots 的产品。提示:只需要用带有三个 % 符号的 LIKE 即可。

 SELECT prod_name, prod_desc
 FROM Products
 WHERE prod_desc LIKE '%toy%carrots%';

20

别名的常见用法是在检索出的结果中重命名表的列字段(为了符合特定的报表要求或客户需求)。编写 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_city AS vcity, vend_address AS vaddress
 FROM Vendors
 ORDER BY vend_name;

21

我们的示例商店正在进行打折促销,所有产品均降价 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;

22

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

 SELECT cust_id, customer_name, UPPER(LEFT(cust_contact,2) + LEFT(cust_city,3)) AS user_login
 FROM Customers;

23

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

 SELECT order_num, order_date
 FROM Orders
 WHERE DATEPART(yy,order_date) = 2020 AND DATEPART (mm,order_date) = 1
 ORDER BY order_date;

24

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

 SELECT sum(quantity)
 FROM OrderItems;

25

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

 SELECT sum(quantity)
 FROM OrderItems
 WHERE prod_id = 'BR01';

26

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

 SELECT MAX(prod_price) AS max_price
 FROM Products
 WHERE prod_price <= 10;

27

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

 SELECT order_num, COUNT(order_num) AS order_lines
 FROM OrderItems
 GROUP BY order_num
 ORDER BY order_lines;

28

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

 SELECT min(prod_price) AS cheapest_item
 FROM Products
 GROUP BY vend_id
 ORDER BY cheapest_item;

29

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

 SELECT order_num
 FROM OrderItems
 GROUP BY order_num
 HAVING sum(quantity) >= 100;

30

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

 SELECT order_num, sum(item_price * quantity)
 FROM OrderItems
 GROUP BY order_num
 HAVING sum(item_price * quantity) >= 1000;

31

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

 SELECT order_num, COUNT(*) AS items
 FROM OrderItems
 GROUP BY items
 HAVING COUNT(*) >= 3
 ORDER BY items, order_num;

GROUP BY 后面不应该是别名

32

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

 SELECT cust_id
 FROM Orders
 WHERE order_num IN (SELECT order_num
                     FROM OrderItems
                     WHERE item_price >= 10);

33

你想知道订购 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');

34

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

 SELECT cust_id, order_date, (SELECT cust_email
                              FROM Customers
                              WHERE cust_id = Orders.cust_id) AS Cemail
 FROM Orders
 WHERE order_num IN (SELECT order_num
                     FROM OrderItems
                     WHERE prod_id = 'BR01');

35

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

 SELECT cust_id, sum(quantity * item_price) AS total_ordered
 FROM Orders,OrderItems
 WHERE Orders.order_num = OrderItems.order_num
 GROUP BY cust_id
 ORDER BY total_ordered DESC;

36

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

 SELECT prod_name, (SELECT SUM(quantity)
                    FROM OrderItems
                    WHERE Products.prod_id = OrderItems.prod_id) AS quant_sold
 FROM Products;

37

编写 SQL 语句,返回 Customers 表中的顾客名称(cust_name)和Orders 表中的相关订单号(order_num),并 按顾客名称再按订单号对结果进行排序。实际上是尝试两次,一次使用简单的等联结语法,一次使用 INNER JOIN。

 (1)
 SELECT cust_name, order_num
 FROM Customers, Orders
 WHERE Customers.cust_id = Orders.cust_id;
 (2)
 SELECT cust_name, order_num
 FROM Customers
 INNER JOIN Orders ON Customers.cust_id = Orders.cust_id;

38

我们来让上一题变得更有用些。除了返回顾客名称和订单号,添加第三列 OrderTotal,其中包含每个订单的总价。有两种方法可以执行此操作:使用 OrderItems 表的子查询来创建 OrderTotal 列,或者将 OrderItems 表与现有表联结并使用聚合函数。提示:请注意需要使用完全限定列名的地方。

(1)
 SELECT cust_name, order_num, (SELECT sum(quantity * item_price)
                               FROM OrderItems
                               WHERE OrderItems.order_num = Orders.order_num) AS OrderTotal
 FROM Customers, Orders
 WHERE Customers.cust_id = Orders.cust_id;
(2)
 SELECT cust_name, Orders.order_num, sum(quantity * item_price) AS OrderTotal
 FROM Customers, Orders, OrderItems
 WHERE Customers.cust_id = Orders.cust_id AND Orders.order_num = OrderItems.order_num
 GROUP BY cust_name, Orders.order_num;

39

我们重新看一下第 33 道挑战题编写 SQL 语句,检索订购产品BR01 的日期,这一次使用联结和简单的等联结语法。输出应该与第11 课的输出相同。

 SELECT cust_id, order_date
 FROM Orders, OrderItems
 WHERE Orders.order_num = OrderItems.order_num AND prod_id = 'BR01';

40

很有趣,我们再试一次。重新创建为第 34 道挑战题 编写的 SQL 语句,这次使用 ANSI 的 INNER JOIN 语法。在之前编写的代码中使用了两个嵌套的子查询。要重新创建它,需要两个 INNER JOIN 语句,每个语句的格式类似于本课讲到的 INNER JOIN 示例,而且不要忘记WHERE 子句可以通过 prod_id 进行过滤。

 SELECT cust_id, order_date, cust_email
 FROM Orders
 INNER JOIN OrderItems ON Orders.order_num = OrderItems.order_num 
 INNER JOIN Customers ON Orders.cust_id = Customers.cust_id
 WHERE prod_id = 'BR01';

41

再让事情变得更加有趣些,我们将混合使用联结、聚合函数和分组。准备好了吗?回到第 10 课,当时的挑战是要求查找值等于或大于 1000的所有订单号。这些结果很有用,但更有用的是订单数量至少达到这个数的顾客名称。因此,编写 SQL 语句,使用联结从 Customers表返回顾客名称(cust_name),并从 OrderItems 表返回所有订单的总价。 提示:要联结这些表,还需要包括 Orders 表(因为 Customers 表与 OrderItems 表不直接相关,Customers 表与 Orders 表相关,而Orders 表与 OrderItems 表相关)。不要忘记 GROUP BY 和 HAVING,并按顾客名称对结果进行排序。你可以使用简单的等联结或 ANSI 的INNER JOIN 语法。或者,如果你很勇敢,请尝试使用两种方式编写。

(1)
 SELECT cust_name, sum(quantity * item_price) 
 FROM Customers, OrderItems, Orders
 WHERE Customers.cust_id = Orders.cust_id 
   AND OrderItems.order_num = Orders.order_num
 GROUP BY cust_name
 HAVING sum(quantity * item_price) >=1000;
(2)
 SELECT cust_name, sum(quantity * item_price) 
 FROM Orders
 INNER JOIN OrderItems ON Orders.order_num = OrderItems.order_num
 INNER JOIN Customers ON Customers.cust_id = Orders.cust_id
 GROUP BY cust_name
 HAVING sum(quantity * item_price) >=1000;

42

使用 INNER JOIN 编写 SQL语句,以检索每个顾客的名称(Customers表中的 cust_name)和所有的订单号(Orders 表中的 order_num)。

 SELECT cust_name, order_num
 FROM Customers
 INNER JOIN Orders ON Orders.cust_id = Customers.cust_id;

43

修改刚刚创建的 SQL 语句,仅列出所有顾客,即使他们没有下过订单。

 SELECT cust_name, order_num
 FROM Customers
 LEFT OUTER JOIN Orders ON Orders.cust_id = Customers.cust_id;

44

使用 OUTER JOIN 联结 Products 表和 OrderItems 表,返回产品名称(prod_name)和与之相关的订单号(order_num)的列表,并按商品名称排序。

 SELECT prod_name, order_num
 FROM Products
 LEFT OUTER JOIN OrderItems ON Products.prod_id = OrderItems.prod_id;

45

修改上一题中创建的 SQL 语句,使其返回每一项产品的总订单数(不是订单号)。

 SELECT prod_name, count(order_num)
 FROM products
 LEFT OUTER JOIN OrderItems ON Products.prod_id = OrderItems.prod_id
 GROUP BY prod_name;

46

编写 SQL语句,列出供应商(Vendors 表中的 vend_id)及其可供产品的数量,包括没有产品的供应商。你需要使用 OUTER JOIN 和 COUNT()聚合函数来计算 Products 表中每种产品的数量。注意:vend_id 列会显示在多个表中,因此在每次引用它时都需要完全限定它。

 SELECT Vendors.vend_id, count(prod_id)
 FROM Vendors
 LEFT OUTER JOIN Products ON Vendors.vend_id = Products. vend_id
 GROUP BY Vendors.vend_id;

47

编写 SQL 语句,将两个 SELECT 语句结合起来,以便从 OrderItems表中检索产品 ID(prod_id)和 quantity。其中,一个 SELECT 语句过滤数量为 100 的行,另一个 SELECT 语句过滤 ID 以 BNBG 开头的产品。按产品 ID 对结果进行排序。

 SELECT quantity, prod_id
 FROM OrderItems
 WHERE quantity = 100
 INTERSECT
 SELECT quantity, prod_id
 FROM OrderItems
 WHERE prod_id LIKE 'BNBG%';

48

重写刚刚创建的 SQL 语句,仅使用单个 SELECT 语句。

 SELECT quantity, prod_id
 FROM OrderItems
 WHERE quantity = 100 AND prod_id LIKE 'BNBG%';

49

编写 SQL 语句,组合 Products 表中的产品名称(prod_name)和 Customers 表中的顾客名称(cust_name)并返回,然后按产品名称对结果进行排序。

 SELECT prod_name
 FROM Products
 UNION
 SELECT cust_name
 WHERE Customers
 ORDER BY prod_name;

50

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

 SELECT cust_name, cust_contact, cust_email
 FROM Customers
 WHERE cust_state = 'MI'
 ORDER BY cust_name;
 UNION
 SELECT cust_name, cust_contact, cust_email
 FROM Customers
 WHERE cust_state = 'IL'ORDER BY cust_name;

第一个SELECT语句最后面不应该加ORDER BY语句,ORDER BY语句用改放在最后面且只能写一个。

51

美国各州的缩写应始终用大写。编写 SQL语句来更新所有美国地址,包括供应商状态(Vendors 表中的 vend_state)和顾客状态(Customers表中的 cust_state),使它们均为大写。

 UPDATE Vandors
    SET vend_state = UPPER(vend_state)
 WHERE vend_state = 'USA';
 UPDATE Customers
    SET cust_state
 WHERE cust_state = 'USA';

52

创建一个名为 CustomersWithOrders 的视图,其中包含 Customers表中的所有列,但仅仅是那些已下订单的列。提示:可以在 Orders表上使用 JOIN 来仅仅过滤所需的顾客,然后使用 SELECT 来确保拥有正确的数据。

 CREATE VIEW CustomersWithOrders AS
 SELECT *
 FROM Customers
 INNER JOIN Orders ON Orders.cust_id = Customers.cust_id;

53

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

 CREATE VIEW OrderItemsExpanded AS
 SELECT order_num,
        prod_id,
        quantity,
        item_price,
        quantity*item_price AS expanded_price
 FROM OrderItems
 ORDER BY order_num;

视图中不允许出现ORDER BY语句。

Posts in this Series