Wonderful Sql

Wonderful Sql

一. 初识数据库

练习题

1.1 编写一条 CREATE TABLE 语句,用来创建一个包含表 1-A 中所列各项的表 Addressbook (地址簿),并为 regist_no (注册编号)列设置主键约束

表1-A 表 Addressbook (地址簿)中的列

Wonderful Sql_第1张图片

DROP TABLE IF EXISTS Adressbook;

CREATE TABLE Adressbook
(regist_no	INTEGER	NOT NULL,
name	VARCHAR(128) NOT NULL,
adress	VARCHAR(256) NOT NULL,
tel_no CHAR(10),
mail_adress	CHAR(20),
PRIMARY KEY (regist_no));

DESC Adressbook;
Field Type Null Key Default Extra
0 regist_no int(11) NO PRI None
1 name varchar(128) NO None
2 adress varchar(256) NO None
3 tel_no char(10) YES None
4 mail_adress char(20) YES None

1.2 假设在创建练习1.1中的 Addressbook 表时忘记添加如下一列 postal_code (邮政编码)了,请编写 SQL 把此列添加到 Addressbook 表中。

列名 : postal_code

数据类型 :定长字符串类型(长度为 8)

约束 :不能为 NULL

ALTER TABLE Adressbook ADD COLUMN postal_code CHAR(8) NOT NULL;
Field Type Null Key Default Extra
0 regist_no int(11) NO PRI None
1 name varchar(128) NO None
2 adress varchar(256) NO None
3 tel_no char(10) YES None
4 mail_adress char(20) YES None
5 postal_code char(8) NO None

1.3 填空题

请补充如下 SQL 语句来删除 Addressbook 表。

(    ) table Addressbook;
DROP table Addressbook;

1.4 判断题

是否可以编写 SQL 语句来恢复删除掉的 Addressbook 表?

不使用工具无法恢复,只能通过运行建表语句重新创建

二. 基础查询与排序

练习题 - 第一部分

2.1 编写一条SQL语句,从 product(商品) 表中选取出“登记日期(regist_date)在2009年4月28日之后”的商品,查询结果要包含 product nameregist_date 两列。

SELECT product_name, regist_date
  FROM product
 WHERE regist_date > '2009-04-28';
product_name regist_date
0 T恤 2009-09-20
1 打孔器 2009-09-11
2 菜刀 2009-09-20
3 叉子 2009-09-20
4 圆珠笔 2009-11-11

2.2 请说出对product 表执行如下3条SELECT语句时的返回结果。

SELECT *
  FROM product
 WHERE purchase_price = NULL;

SELECT *
  FROM product
 WHERE purchase_price <> NULL;

SELECT *
  FROM product
 WHERE product_name > NULL;

product_id product_name product_type sale_price purchase_price regist_date

product_id product_name product_type sale_price purchase_price regist_date

product_id product_name product_type sale_price purchase_price regist_date

2.3 2.2.3章节中的SELECT语句能够从product 表中取出“销售单价(sale_price)比进货单价(purchase_price`)高出500日元以上”的商品。请写出两条可以得到相同结果的SELECT语句。执行结果如下所示:

product_name | sale_price | purchase_price 
-------------+------------+------------
T恤衫        |   1000    | 500
运动T恤      |    4000    | 2800
高压锅       |    6800    | 5000
SELECT product_name, sale_price, purchase_price
  FROM product
 WHERE sale_price - purchase_price >= 500;
SELECT product_name, sale_price, purchase_price
  FROM product
 WHERE sale_price >= purchase_price + 500;

2.4 请写出一条SELECT语句,从 product 表中选取出满足“销售单价打九折之后利润高于 100 日元的办公用品和厨房用具”条件的记录。查询结果要包括 product_name列、product_type 列以及销售单价打九折之后的利润(别名设定为 profit)。

提示:销售单价打九折,可以通过 sale_price 列的值乘以0.9获得,利润可以通过该值减去 purchase_price 列的值获得。

SELECT product_name, product_type,
       sale_price * 0.9 - purchase_price AS profit
  FROM product
 WHERE sale_price * 0.9 - purchase_price > 100
       AND (   product_type = '办公用品'
           OR product_type = '厨房用具');
product_name product_type profit
0 打孔器 办公用品 130.0
1 高压锅 厨房用具 1120.0

练习题 - 第二部分

2.5 请指出下述SELECT语句中所有的语法错误。

SELECT product_id, SUM(product_name)
--本SELECT语句中存在错误。
  FROM product 
 GROUP BY product_type 
 WHERE regist_date > '2009-09-01';

SUM函数仅适用于数字类型的字段, 不能对product_name使用SUM聚合

SELECT子句中的product_id字段为非聚合函数, 不在GROUP BY的字段列表product_type

WHERE子句应该出现在GROUP BY之前, FROM之后

2.6 请编写一条SELECT语句,求出销售单价( sale_price 列)合计值大于进货单价( purchase_price 列)合计值1.5倍的商品种类。执行结果如下所示。

product_type | sum  | sum 
-------------+------+------
衣服         | 5000 | 3300
办公用品      |  600 | 320

Wonderful Sql_第2张图片

SELECT product_type, SUM(sale_price), SUM(purchase_price)
  FROM product
GROUP BY product_type
HAVING SUM(sale_price) > SUM(purchase_price) * 1.5;
product_type SUM(sale_price) SUM(purchase_price)
0 衣服 5000.0 3300.0
1 办公用品 600.0 320.0

2.7 此前我们曾经使用SELECT语句选取出了product(商品)表中的全部记录。当时我们使用了 ORDER BY 子句来指定排列顺序,但现在已经无法记起当时如何指定的了。请根据下列执行结果,思考 ORDER BY 子句的内容。

Wonderful Sql_第3张图片

SELECT *
  FROM product
ORDER BY regist_date IS NOT NULL, regist_date DESC, sale_price;
product_id product_name product_type sale_price purchase_price regist_date
0 0003 运动T恤 衣服 4000 2800.0 None
1 0008 圆珠笔 办公用品 100 NaN 2009-11-11
2 0006 叉子 厨房用具 500 NaN 2009-09-20
3 0001 T恤 衣服 1000 500.0 2009-09-20
4 0004 菜刀 厨房用具 3000 2800.0 2009-09-20
5 0002 打孔器 办公用品 500 320.0 2009-09-11
6 0005 高压锅 厨房用具 6800 5000.0 2009-01-15
7 0007 擦菜板 厨房用具 880 790.0 2008-04-28

三. 复杂一点的查询

练习题 - 第一部分

3.1 创建出满足下述三个条件的视图(视图名称为 ViewPractice5_1)。使用 product(商品)表作为参照表,假设表中包含初始状态的 8 行数据。

  • 条件 1:销售单价大于等于 1000 日元。
  • 条件 2:登记日期是 2009 年 9 月 20 日。
  • 条件 3:包含商品名称、销售单价和登记日期三列。

对该视图执行 SELECT 语句的结果如下所示。

SELECT * FROM ViewPractice5_1;

执行结果

product_name | sale_price | regist_date
-------------+------------+------------
T恤          |   1000    | 2009-09-20
菜刀         |    3000    | 2009-09-20
CREATE VIEW ViewPractice5_1 (product_name, sale_price, regist_date) AS
SELECT product_name, sale_price, regist_date
    FROM product
WHERE sale_price >= 1000 
    AND regist_date='2009-09-20';

SELECT * FROM ViewPractice5_1;
product_name sale_price regist_date
0 T恤 1000 2009-09-20
1 菜刀 3000 2009-09-20

3.2 向习题一中创建的视图 ViewPractice5_1 中插入如下数据,会得到什么样的结果?为什么?

INSERT INTO ViewPractice5_1 VALUES (' 刀子 ', 300, '2009-11-02');
# Time Action Message Duration / Fetch
1 0 00:38:48 INSERT INTO ViewPractice5_1 VALUES (’ 刀子 ', 300, ‘2009-11-02’) Error Code: 1423. Field of view ‘shop.viewpractice5_1’ underlying table doesn’t have a default value 0.000 sec

查询结果会报错, 由于视图只是原表的一个窗口, 视图中的字段与原表不重合, 原表中有NOT NULL的字段没有给默认值导致报错, 只有插入命令对原表能插入成功时, 才能对视图插入成功

3.3 请根据如下结果编写 SELECT 语句,其中 sale_price_avg 列为全部商品的平均销售单价。

Wonderful Sql_第4张图片

SELECT product_id, product_name, product_type, sale_price,
       (SELECT AVG(sale_price) FROM product) AS sale_price_avg
FROM product;
product_id product_name product_type sale_price sale_price_avg
0 0001 T恤 衣服 1000 2097.5
1 0002 打孔器 办公用品 500 2097.5
2 0003 运动T恤 衣服 4000 2097.5
3 0004 菜刀 厨房用具 3000 2097.5
4 0005 高压锅 厨房用具 6800 2097.5
5 0006 叉子 厨房用具 500 2097.5
6 0007 擦菜板 厨房用具 880 2097.5
7 0008 圆珠笔 办公用品 100 2097.5

3.4 请根据习题一中的条件编写一条 SQL 语句,创建一幅包含如下数据的视图(名称为AvgPriceByType)。

Wonderful Sql_第5张图片

提示:其中的关键是 sale_price_avg_type 列。与习题三不同,这里需要计算出的 是各商品种类的平均销售单价。这与使用关联子查询所得到的结果相同。 也就是说,该列可以使用关联子查询进行创建。问题就是应该在什么地方使用这个关联子查询。

CREATE VIEW AvgPriceByType AS
SELECT product_id, product_name, product_type, sale_price,
       (SELECT AVG(sale_price) 
			FROM product AS p2 
		WHERE p1.product_type=p2.product_type) AS sale_price_avg
FROM product AS p1;

SELECT * FROM AvgPriceByType;
product_id product_name product_type sale_price sale_price_avg
0 0001 T恤 衣服 1000 2500.0
1 0002 打孔器 办公用品 500 300.0
2 0003 运动T恤 衣服 4000 2500.0
3 0004 菜刀 厨房用具 3000 2795.0
4 0005 高压锅 厨房用具 6800 2795.0
5 0006 叉子 厨房用具 500 2795.0
6 0007 擦菜板 厨房用具 880 2795.0
7 0008 圆珠笔 办公用品 100 300.0

练习题 - 第二部分

3.5 判断题

四则运算中含有 NULL 时(不进行特殊处理的情况下),运算结果是否必然会变为NULL ?

3.6 对本章中使用的 product(商品)表执行如下 2 条 SELECT 语句,能够得到什么样的结果呢?

SELECT product_name, purchase_price
  FROM product
 WHERE purchase_price NOT IN (500, 2800, 5000);

SELECT product_name, purchase_price
  FROM product
 WHERE purchase_price NOT IN (500, 2800, 5000, NULL);
product_name purchase_price
0 打孔器 320
1 擦菜板 790
product_name purchase_price
IN或NOT IN谓词无法选取NULL的数据,也无法与NULL作比较,可以使用特定的谓词IS NULL或IS NOT NULL搭配逻辑运算符实现

3.7 按照销售单价( sale_price )对练习 3.6 中的 product(商品)表中的商品进行如下分类。

  • 低档商品:销售单价在1000日元以下(T恤衫、办公用品、叉子、擦菜板、 圆珠笔)
  • 中档商品:销售单价在1001日元以上3000日元以下(菜刀)
  • 高档商品:销售单价在3001日元以上(运动T恤、高压锅)

请编写出统计上述商品种类中所包含的商品数量的 SELECT 语句,结果如下所示。

执行结果

low_price | mid_price | high_price
----------+-----------+------------
        5 |         1 |         2
SELECT SUM(CASE WHEN sale_price <= 1000 THEN 1 ELSE 0 END) AS low_price,
       SUM(CASE WHEN sale_price BETWEEN 1001 AND 3000 THEN 1 ELSE 0 END) AS mid_price,
       SUM(CASE WHEN sale_price >= 3001 THEN 1 ELSE 0 END) AS high_price
FROM product;
low_price mid_price high_price
0 5.0 1.0 2.0

你可能感兴趣的:(sql,数据库,mysql)