SQL必知必会挑战题答案

创建数据表

-- -----------------------------------------
-- Sams Teach Yourself SQL in 10 Minutes
-- http://forta.com/books/0672336073/
-- Example table creation scripts for MySQL.
-- ------------------------------------------- ----------------------
-- 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 Customers tabl

-- -------------------------------------------
-- Sams Teach Yourself SQL in 10 Minutes
-- http://forta.com/books/0672336073/
-- Example table population scripts for MySQL.
-- --------------------------------------------- ------------------------
-- 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', 'sales@villagetoys.com');
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', 'jjones@fun4all.com');
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', 'dstephens@fun4all.com');
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, '2012-05-01', '1000000001');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20006, '2012-01-12', '1000000003');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20007, '2012-01-30', '1000000004');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20008, '2012-02-03', '1000000005');
INSERT INTO Orders(order_num, order_date, cust_id)
VALUES(20009, '2012-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);

第 2 课 检索数据

    1. 编写 SQL 语句,从 Customers 表中检索所有的 ID(cust_id)。
SELECT cust_id
FROM Customers;
    1. OrderItems 表包含了所有已订购的产品(有些已被订购多次)。编写SQL 语句,检索并列出已订购产品(prod_id)的清单(不用列每个订单,只列出不同产品的清单)。提示:最终应该显示 7 行。
SELECT DISTINCT prod_id
FROM OrderItems;
    1. 编写 SQL语句,检索 Customers 表中所有的列,再编写另外的 SELECT语句,仅检索顾客的 ID。使用注释,注释掉一条 SELECT 语句,以便运行另一条 SELECT 语句。(当然,要测试这两个语句。)
SELECT *
# SELECT cust_id
FROM Customers;

第 3 课 排序检索数据

    1. 编写 SQL 语句,从 Customers 中检索所有的顾客名称(cust_names),并按从 Z 到 A 的顺序显示结果。
SELECT cust_name
FROM Customers
ORDER BY cust_name DESC;
    1. 编写 SQL 语句,从 Orders 表中检索顾客 ID(cust_id)和订单号(order_num),并先按顾客 ID 对结果进行排序,再按订单日期倒序排列。
SELECT cust_id, order_num
FROM Orders
ORDER BY cust_id, order_date DESC;
    1. 显然,我们的虚拟商店更喜欢出售比较贵的物品,而且这类物品有很多。编写 SQL 语句,显示 OrderItems 表中的数量和价格(item_price),并按数量由多到少、价格由高到低排序。
SELECT quantity, item_price
FROM OrderItems
ORDER BY quantity DESC, item_price DESC;
    1. 下面的 SQL 语句有问题吗?(尝试在不运行的情况下指出。)
SELECT vend_name,
FROM Vendors
ORDER vend_name DESC;

vend_name 后不应有逗号(逗号仅用于分隔多个列),并且 ORDER 后缺少了 BY。

第 4 课 过滤

    1. 编写 SQL 语句,从 Products 表中检索产品 ID(prod_id)和产品名称(prod_name),只返回价格为 9.49 美元的产品。
SELECT prod_id, prod_name
FROM Products
WHERE prod_price = 9.49;
    1. 编写 SQL 语句,从 Products 表中检索产品 ID(prod_id)和产品名称(prod_name),只返回价格为 9 美元或更高的产品。
SELECT prod_id, prod_name
FROM Products
WHERE prod_price >= 9;
    1. 结合第 3 课和第 4 课编写 SQL 语句,从 OrderItems 表中检索出所有不同订单号(order_num),其中包含 100 个或更多的产品。
SELECT DISTINCT order_num
FROM OrderItems
WHERE quantity >=100;
    1. 编写 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;

第 5 课 高级数据过滤

    1. 编写 SQL 语句,从 Vendors 表中检索供应商名称(vend_name),仅返回加利福尼亚州的供应商(这需要按国家[USA]和州[CA]进行过滤,没准其他国家也存在一个加利福尼亚州)。提示:过滤器需要匹配字符串。
SELECT vend_name
FROM Vendors
WHERE vend_country = 'USA' AND vend_state = 'CA';
    1. 编写 SQL 语句,查找所有至少订购了总量 100 个的 BR01、BR02 或BR03 的订单。你需要返回 OrderItems 表的订单号(order_num)、产品 ID(prod_id)和数量,并按产品 ID 和数量进行过滤。提示:根据编写过滤器的方式,可能需要特别注意求值顺序。
--解法 1
SELECT order_num, prod_id, quantity
FROM OrderItems
WHERE (prod_id='BR01' OR prod_id='BR02' OR prod_id='BR03') AND quantity >=100; --解法 2
SELECT order_num, prod_id, quantity
FROM OrderItems
WHERE prod_id IN ('BR01','BR02','BR03') AND quantity >=100;
    1. 现在,我们回顾上一课的挑战题。编写 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;
    1. 下面的 SQL 语句有问题吗?(尝试在不运行的情况下指出。)
SELECT vend_name
FROM Vendors
ORDER BY vend_name
WHERE vend_country = 'USA' AND vend_state = 'CA';

ORDER BY 必须跟在 WHERE 子句之后。

第 6 课 用通配符进行过滤

    1. 编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中包含 toy 一词的产品。
SELECT prod_name, prod_desc
FROM Products
WHERE prod_desc LIKE '%toy%';
    1. 反过来再来一次。编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回描述中未出现 toy 一词的产品。这次,按产品名称对结果进行排序。
SELECT prod_name, prod_desc
FROM Products
WHERE NOT prod_desc LIKE '%toy%'
ORDER BY prod_name;
    1. 编写 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%';
    1. 来个比较棘手的。我没有特别向你展示这个语法,而是想看看你根据目前已学的知识是否可以找到答案。编写 SQL 语句,从 Products 表中检索产品名称(prod_name)和描述(prod_desc),仅返回在描述

      中以先后顺序同时出现 toy 和 carrots 的产品。提示:只需要用带有三个 % 符号的 LIKE 即可。

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

第 7 课 创建计算字段

    1. 别名的常见用法是在检索出的结果中重命名表的列字段(为了符合特定的报表要求或客户需求)。编写 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;
    1. 我们的示例商店正在进行打折促销,所有产品均降价 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;

第 8 课 使用函数处理数据

    1. 我们的商店已经上线了,正在创建顾客账户。所有用户都需要登录名,默认登录名是其名称和所在城市的组合。编写 SQL 语句,返回顾客 ID(cust_id)、顾客名称(customer_name)和登录名(user_login),其中登录名全部为大写字母,并由顾客联系人的前两个字符(cust_contact)和其所在城市的前三个字符(cust_city)组成。例如,我的登录名是 BEOAK(Ben Forta,居住在 Oak Park)。提示:需要使用函数、拼接和别名。
-- DB2, PostgreSQL
SELECT cust_id, cust_name, UPPER(LEFT(cust_contact, 2)) || UPPER(LEFT(cust_city, 3)) AS
user_login
FROM customers; -- Oracle, SQLite
SELECT cust_id, cust_name, UPPER(SUBSTR(cust_contact, 1, 2)) || UPPER(SUBSTR(cust_city, 1, 3)) AS
user_login
FROM customers; -- MySQL
SELECT cust_id, cust_name, CONCAT(UPPER(LEFT(cust_contact, 2)), UPPER(LEFT(cust_city, 3))) AS
user_login
FROM customers; -- SQL Server
SELECT cust_id, cust_name, UPPER(LEFT(cust_contact, 2)) + UPPER(LEFT(cust_city, 3)) AS
user_login
FROM customers;
    1. 编写 SQL 语句,返回 2020 年 1 月的所有订单的订单号(order_num)和订单日期(order_date),并按订单日期排序。你应该能够根据目前已学的知识来解决此问题,但也可以开卷查阅 DBMS 文档。
-- DB2, MariaDB, MySQL
SELECT order_num, order_date
FROM Orders
WHERE YEAR(order_date) = 2020 AND MONTH(order_date) = 1
ORDER BY order_date; -- Oracle, PostgreSQL
SELECT order_num, order_date
FROM Orders
WHERE EXTRACT(year FROM order_date) = 2020 AND EXTRACT(month FROM
order_date) = 1
ORDER BY order_date; -- PostgreSQL
SELECT order_num, order_date
FROM Orders
WHERE DATE_PART('year', order_date) = 2020 AND DATE_PART('month', order_date) = 1
ORDER BY order_num; -- SQL Server
SELECT order_num, order_date
FROM Orders
WHERE DATEPART(yy, order_date) = 2020 AND DATEPART(mm, order_date) = 1
ORDER BY order_date; -- SQLite
SELECT order_num
FROM Orders
WHERE strftime('%Y', order_date) = '2020' AND strftime('%m', order_date) = '01';

第 9 课 汇总数据

    1. 编写 SQL 语句,确定已售出产品的总数(使用 OrderItems 中的quantity 列)。
SELECT SUM(quantity) AS items_ordered
FROM OrderItems;
    1. 修改刚刚创建的语句,确定已售出产品项(prod_item)BR01 的总数。
SELECT SUM(quantity) AS items_ordered
FROM OrderItems
WHERE prod_id = 'BR01';
    1. 编写 SQL 语句,确定 Products 表中价格不超过 10 美元的最贵产品的价格(prod_price)。将计算所得的字段命名为 max_price。
SELECT MAX(prod_price) AS max_price
FROM Products
WHERE prod_price <= 10;

第 10 课 分组数据

    1. 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;
    1. 编写 SQL 语句,返回名为 cheapest_item 的字段,该字段包含每个供应商成本最低的产品(使用 Products 表中的 prod_price),然后从最低成本到最高成本对结果进行排序。
SELECT vend_id, MIN(prod_price) AS cheapest_item
FROM Products
GROUP BY vend_id
ORDER BY cheapest_item;
    1. 确定最佳顾客非常重要,请编写 SQL 语句,返回至少含 100 项的所有订单的订单号(OrderItems 表中的 order_num)。
SELECT order_num
FROM OrderItems
GROUP BY order_num
HAVING SUM(quantity) >= 100
ORDER BY order_num;
    1. 确定最佳顾客的另一种方式是看他们花了多少钱。编写 SQL 语句,返回总价至少为 1000 的所有订单的订单号(OrderItems 表中的order_num)。提示:需要计算总和(item_price 乘以 quantity)。按订单号对结果进行排序。
SELECT order_num, SUM(item_price*quantity) AS total_price
FROM OrderItems
GROUP BY order_num
HAVING SUM(item_price*quantity) >= 1000
ORDER BY order_num;
    1. 下面的 SQL 语句有问题吗?(尝试在不运行的情况下指出。)
SELECT order_num, COUNT(*) AS items
FROM OrderItems
GROUP BY items
HAVING COUNT(*) >= 3
ORDER BY items, order_num;

GROUP BY 项是错误的。GROUP BY 必须是实际列,而不是用于执行汇总计算的列。允许使用 GROUP BY order_num。

第 11 课 使用子查询

    1. 使用子查询,返回购买价格为 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);
    1. 你想知道订购 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;
    1. 现在我们让它更具挑战性。在上一个挑战题,返回购买 prod_id 为BR01 的产品的所有顾客的电子邮件(Customers 表中的 cust_email)。提示:这涉及 SELECT 语句,最内层的从 OrderItems 表返回 order_num,中间的从 Customers 表返回 cust_id。
SELECT 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'));
    1. 我们需要一个顾客 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;
    1. 再来。编写 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;

第 12 课 联结表

    1. 编写 SQL 语句,返回 Customers 表中的顾客名称(cust_name)和Orders 表中的相关订单号(order_num),并按顾客名称再按订单号对结果进行排序。实际上是尝试两次,一次使用简单的等联结语法,一次使用 INNER JOIN。
-- 等值连接语法
SELECT cust_name, order_num
FROM Customers, Orders
WHERE Customers.cust_id = Orders.cust_id
ORDER BY cust_name, order_num; -- ANSI INNER JOIN 语法
SELECT cust_name, order_num
FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id
ORDER BY cust_name, order_num;
    1. 我们来让上一题变得更有用些。除了返回顾客名称和订单号,添加第三列 OrderTotal,其中包含每个订单的总价。有两种方法可以执行此操作:使用 OrderItems 表的子查询来创建 OrderTotal 列,或者将 OrderItems 表与现有表联结并使用聚合函数。提示:请注意需要使用完全限定列名的地方。
-- 使用子查询的解法
SELECT cust_name, order_num, (SELECT Sum(item_price*quantity) FROM OrderItems WHERE Orders.order_num=OrderItems.order_num) AS OrderTotal
FROM Customers, Orders
WHERE Customers.cust_id = Orders.cust_id
ORDER BY cust_name, order_num; -- 使用联结的解法
SELECT cust_name, Orders.order_num, Sum(item_price*quantity) 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
ORDER BY cust_name, order_num;
    1. 我们重新看一下第 11 课的挑战题 2。编写 SQL 语句,检索订购产品BR01 的日期,这一次使用联结和简单的等联结语法。输出应该与第11 课的输出相同。
SELECT cust_id, order_date
FROM Orders, OrderItems
WHERE Orders.order_num = OrderItems.order_num AND prod_id = 'BR01'
ORDER BY order_date;
    1. 很有趣,我们再试一次。重新创建为第 11 课挑战题 3 编写的 SQL 语句,这次使用 ANSI 的 INNER JOIN 语法。在之前编写的代码中使用了两个嵌套的子查询。要重新创建它,需要两个 INNER JOIN 语句,每个语句的格式类似于本课讲到的 INNER JOIN 示例,而且不要忘记WHERE 子句可以通过 prod_id 进行过滤。
SELECT cust_email
FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id INNER JOIN OrderItems ON Orders.order_num = OrderItems.order_num
WHERE prod_id = 'BR01';
    1. 再让事情变得更加有趣些,我们将混合使用联结、聚合函数和分组。准备好了吗?回到第 10 课,当时的挑战是要求查找值等于或大于 1000的所有订单号。这些结果很有用,但更有用的是订单数量至少达到这个数的顾客名称。因此,编写 SQL 语句,使用联结从 Customers表返回顾客名称(cust_name),并从 OrderItems 表返回所有订单的总价。提示:要联结这些表,还需要包括 Orders 表(因为 Customers 表 与 OrderItems 表不直接相关,Customers 表与 Orders 表相关,而Orders 表与 OrderItems 表相关)。不要忘记 GROUP BY 和 HAVING,并按顾客名称对结果进行排序。你可以使用简单的等联结或 ANSI 的INNER JOIN 语法。或者,如果你很勇敢,请尝试使用两种方式编写。
-- 等值连接语法
SELECT cust_name, SUM(item_price*quantity) AS total_price
FROM Customers, Orders, OrderItems
WHERE Customers.cust_id = Orders.cust_id AND Orders.order_num = OrderItems.order_num
GROUP BY cust_name HAVING SUM(item_price*quantity) >= 1000
ORDER BY cust_name;-- ANSI INNER JOIN 语法
SELECT cust_name, SUM(item_price*quantity) AS total_price
FROM Customers INNER JOIN Orders ON Customers.cust_id = Orders.cust_id INNER JOIN OrderItems ON Orders.order_num = OrderItems.order_num
GROUP BY cust_name
HAVING SUM(item_price*quantity) >= 1000
ORDER BY cust_name;

第13 课 创建高级联结

    1. 使用 INNER JOIN 编写 SQL语句,以检索每个顾客的名称(Customers表中的 cust_name)和所有的订单号(Orders 表中的 order_num)。
SELECT cust_name, order_num
FROM Customers
JOIN Orders ON Customers.cust_id = Orders.cust_id
ORDER BY cust_name;
    1. 修改刚刚创建的 SQL 语句,仅列出所有顾客,即使他们没有下过订单。
SELECT cust_name, order_num
FROM Customers LEFT OUTER JOIN Orders ON Customers.cust_id = Orders.cust_id
ORDER BY cust_name;
    1. 使用 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
ORDER BY prod_name;
    1. 修改上一题中创建的 SQL 语句,使其返回每一项产品的总订单数(不是订单号)。
SELECT prod_name, COUNT(order_num) AS orders
FROM Products LEFT OUTER JOIN OrderItems
ON Products.prod_id = OrderItems.prod_id
GROUP BY prod_name
ORDER BY prod_name;
    1. 编写 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;

第14 课 组合查询

    1. 编写 SQL 语句,将两个 SELECT 语句结合起来,以便从 OrderItems表中检索产品 ID(prod_id)和 quantity。其中,一个 SELECT 语句过滤数量为 100 的行,另一个 SELECT 语句过滤 ID 以 BNBG 开头的产品。按产品 ID 对结果进行排序。
SELECT prod_id, quantity FROM OrderItems
WHERE quantity = 100
UNION
SELECT prod_id, quantity FROM OrderItems
WHERE prod_id LIKE 'BNBG%'
ORDER BY prod_id;
    1. 重写刚刚创建的 SQL 语句,仅使用单个 SELECT 语句。
SELECT prod_id, quantity FROM OrderItems
WHERE quantity = 100 OR prod_id LIKE 'BNBG%'
ORDER BY prod_id;
    1. 我知道这有点荒谬,但这节课中的一个注释提到过。编写 SQL 语句,组合 Products 表中的产品名称(prod_name)和 Customers 表中的顾客名称(cust_name)并返回,然后按产品名称对结果进行排序。
SELECT prod_name
FROM Products
UNION
SELECT cust_name
FROM Customers
ORDER BY prod_name;
    1. 下面的 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 语句后的;不应该出现,它将终止该语句。同样,如果将结合 UNION 的 SELECT 语句进行排序,则只能使用一个 ORDER BY,并且它必须跟在最后一个 SELECT 之后。

第15 课 插入数据

  • 使用 INSERT 和指定的列,将你自己添加到 Customers 表中。明确列出要添加哪几列,且仅需列出你需要的列。
-- 显然要用你自己的内容替换。
INSERT INTO Customers(cust_id, cust_name, cust_address, cust_city, cust_state, cust_zip, cust_country, cust_email)
VALUES(1000000042, 'Ben''s Toys', '123 Main Street', 'Oak Park', 'MI', '48237', 'USA', 'ben@forta.com');
    1. 备份 Orders 表和 OrderItems 表。
-- MySQL, MariaDB, Oracle, PostgreSQL, SQLite
CREATE TABLE OrdersBackup AS SELECT * FROM Orders;
CREATE TABLE OrderItemsBackup AS SELECT * FROM OrderItems; -- SQL Server
SELECT * INTO OrdersBackup FROM Orders;
SELECT * INTO OrderItemsBackup FROM OrderItems;

第16 课 更新和删除数据

    1. 美国各州的缩写应始终用大写。编写 SQL语句来更新所有美国地址,包括供应商状态(Vendors 表中的 vend_state)和顾客状态(Customers表中的 cust_state),使它们均为大写。
UPDATE Vendors
SET vend_state = UPPER(vend_state)
WHERE vend_country = 'USA'; UPDATE Customers
SET cust_state = UPPER(cust_state)
WHERE cust_country = 'USA';
    1. 15 课的挑战题 1 要求你将自己添加到 Customers 表中。现在请删除自己。确保使用 WHERE 子句(在 DELETE 中使用它之前,先用 SELECT对其进行测试),否则你会删除所有顾客
-- 首先测试 WHERE,确保它仅选择你要删除的内容。
SELECT * FROM Customers
WHERE cust_id = 1000000042; -- 那就做吧!
DELETE Customers
WHERE cust_id = 1000000042;

第 17 课 创建和操纵表

    1. 在 Vendors 表中添加一个网站列(vend_web)。你需要一个足以容纳URL 的大文本字段。
ALTER TABLE Vendors
ADD vend_web CHAR(100);
    1. 使用 UPDATE 语句更新 Vendor 记录,以便加入网站(你可以编造任何地址)。
UPDATE Vendors
SET vend_web = 'https://google.com/'
WHERE vend_id = 'DLL01';

第 18 课 使用视图

    1. 创建一个名为 CustomersWithOrders 的视图,其中包含 Customers表中的所有列,但仅仅是那些已下订单的列。提示:可以在 Orders表上使用 JOIN 来仅仅过滤所需的顾客,然后使用 SELECT 来确保拥有正确的数据。
CREATE VIEW CustomersWithOrders AS
SELECT Customers.cust_id, Customers.cust_name, Customers.cust_address, Customers.cust_city, Customers.cust_state, Customers.cust_zip, Customers.cust_country, Customers.cust_contact, Customers.cust_email
FROM Customers
JOIN Orders ON Customers.cust_id = Orders.cust_id;
SELECT * FROM CustomersWithOrders;
    1. 下面的 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。如果你想在从视图检索数据的 SELECT中使用 ORDER BY 对数据进行排序,则视图的使用方式与表相同。

SQL必知必会挑战题答案相关推荐

  1. 《SQL必知必会(第5版)》挑战题笔记 | 所用DBMS为Mysql,mysql workbench安装

    文章目录 一.安装 step1:mysql安装 step2:mysql workbench安装 二.下载随书资料 三.代码实战练习 2.2 检索单个列 四.MySQL知识点回顾 五.挑战题 2.9挑战 ...

  2. 根据SQL必知必会学习SQL(MYSQL)

    很久都没有整理SQL语句了,遇到让写SQL语句的题也很迷茫,所以就重拾一下知识,本文章根据SQL必知必会进行梳理 文章目录 一.检索所有列 1.select 1.1检索单个列 1.2 检索多个列 1. ...

  3. 应聘必看——75道逻辑题答案

    应聘必看--75道逻辑题答案 [1]    假设有一个池塘,里面有无穷多的水.现有2个空水壶,容积分别为5升和6升.问题是如何只用这2个水壶从池塘里取得3升的水. 由满6向空5倒,剩1升,把这1升倒5 ...

  4. 【SQL必知必会笔记(3)】SELECT语句的WHERE子句数据过滤操作

    上个笔记主要介绍了利用SELECT语句检索单个/多个/所有列,并利用DISTINCT关键字检索具有唯一性的值.利用LIMIT/OFFSET子句限制结果:以及利用ORDER BY子句排序检索出的数据,主 ...

  5. 【SQL】【读书笔记】《MySQL必知必会》

    本文为<MySQL必知必会>[1]读书笔记,用于总结知识点和框架,仅供参考和交流,如有不妥请联系.由于软件版本更新,书中的一些代码已经不再适用,本文主要从SQL基本语句进行增删减.窗口函数 ...

  6. 《SQL必知必会》查询部分学习笔记

    目录 <SQL必知必会>查询部分学习笔记 1 前言 2 认识SQL 3 检索数据 4 排序检索数据 5 过滤数据 6 高级数据过滤 7 通配符 8 创建计算字段 9 使用函数处理数据 11 ...

  7. SQL必知必会(第五版)

    SQL必知必会 了解SQL 1.数据库 数据库就像是一个容器,存放各种表.需要与DBMS区分 1.1表 一个结构化的清单,存储各种数据. sql全称是struct query language 结构化 ...

  8. 《MySQL必知必会》所有SQL语句图表集合(可作为查询表使用)---已完结

    本篇文章是对<MySQL必知必会>所有语句知识点的图表集合,适合快速查询遗忘的SQL语句. 本文的脉络结构,首先先给出<MySQL必知必会>的目录和本书中用到的数据表的UML图 ...

  9. asp sql ip地址排序_SQL必知必会读书笔记,30分钟入门SQL!

    点击上方SQL数据库开发,关注获取SQL视频教程 SQL专栏 SQL数据库基础知识汇总 SQL数据库高级知识汇总 来源:https://segmentfault.com/p/1210000011760 ...

最新文章

  1. 坦克大战java_清华毕业大佬用一个坦克大战项目讲完了23种设计模式
  2. 火山引擎战略初现,字节跳动打造To B服务双引擎?
  3. [渝粤教育] 广东-国家-开放大学 21秋期末考试物权法10774k1
  4. 最新unity3d中关键概念全解(坐标系,脚本的执行顺序等)
  5. win7修改开机动画
  6. 整理:.NET 性能优化方法总结
  7. Mac好用的截图软件,这就来了!
  8. js substring、substr和slice 截取字符串
  9. 强化学习(一):Q-learning,附源码解读
  10. react 项目的一个ie8兼容性问题
  11. 深入理解java虚拟机(十三)Java Mission Control:可持续在线的监控工具
  12. 微信播放在服务器视频无法播放音乐,解决ios微信浏览器中audio和video音乐视频无法自动播放等问题...
  13. 熊孩子乱敲键盘攻破Linux,“熊孩子”乱敲键盘就攻破了Linux桌面,大神:17年前我就警告过你们...
  14. 基于数字温度传感器的数字温度计 华氏度和摄氏度
  15. 经典语录:二十不勤,三十不立,四十不富,五十而衰靠子助
  16. 基于Xilinx Zynq-7000系列XC7Z035/XC7Z045/XC7Z100高性能SoC处理器设计的高端核心板
  17. 2021011206贾天乐实验三
  18. 浪潮5280m4导轨安装_NF5280M4机架解密:拆装方便和稳定_浪潮 英信NF5280M4(Xeon E5-2620 v3/8GB/300GB*3/16*HSB)_服务器知识学堂-中关村在线...
  19. 同一局域网内ping请求超时
  20. 小米手机怎么录屏?小米手机录屏功能在哪?

热门文章

  1. 徒手撸设计模式-抽象工厂模式
  2. NDK开发之ndk-build命令详解
  3. 发布坐标转换软件OpenCoord的使用第二集-椭球转换
  4. 先进先出页面置换算法的模拟(c++实现)
  5. 【C语言】几道C/C++面试题解析
  6. 我的10年计算机之路
  7. 测绘专业计算机课程,测绘工程有哪些基础课程?
  8. 手把手教你白嫖一个服务器并搭建自己的远程Notebook
  9. 使用免费引流脚本,如何突破引流难的困境
  10. WIN10之右键“管理”报错:该文件没有与之关联的程序来执行该操作,请安装一个程序,或者,如果已安装程序.....