目录
2.1 排序与查询知识汇总
| 用法 | 相关法则 | |||||||||||||
SELECT | 查询并选取出必要数据:
|
| |||||||||||||
WHERE | 条件查询:
| ||||||||||||||
算数运算符 |
|
| |||||||||||||
比较运算符 |
| ||||||||||||||
逻辑运算符 |
|
| |||||||||||||
真值表 | 在遇到条件较复杂的语句时,采用真值表来梳理逻辑关系(TRUE/FALSE/UNKNOW) |
| |||||||||||||
聚合函数 |
|
| |||||||||||||
表分组 | 分组汇总,即将现有的数据按照某列来汇总统计
|
| |||||||||||||
过滤分组 | HAVING子句用于对分组进行过滤,可以使用数字、聚合函数和GROUP BY中指定的列名(聚合键) |
| |||||||||||||
对查询结果进行排序 | 默认为升序序列,降序序列关键字DESC
|
|
2.2 练习题(macOS)
2.2.1 第一部分
准备工作,建表并插入数据:
-- 建表
CREATE TABLE product
(product_id CHAR(4) NOT NULL PRIMARY KEY,
product_name VARCHAR(100) NOT NULL,
product_type VARCHAR(32) NOT NULL,
sale_price INTEGER,
purchase_price INTEGER,
regist_date DATE);
-- 插入数据
INSERT INTO product VALUES('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20');
INSERT INTO product VALUES('0002', '打孔器', '办公用品', 500, 320, '2009-09-11');
INSERT INTO product VALUES('0003', '运动T恤', '衣服', 4000, 2800, NULL);
INSERT INTO product VALUES('0004', '菜刀', '厨房用具', 3000, 2800, '2009-09-20');
INSERT INTO product VALUES('0005', '高压锅', '厨房用具', 6800, 5000, '2009-01-15');
INSERT INTO product VALUES('0006', '叉子', '厨房用具', 500, NULL, '2009-09-20');
INSERT INTO product VALUES('0007', '擦菜板', '厨房用具', 880, 790, '2008-04-28');
INSERT INTO product VALUES('0008', '圆珠笔', '办公用品', 100, NULL, '2009-11-11');
查看结果:
mysql> select * from product;
+------------+--------------+--------------+------------+----------------+-------------+
| product_id | product_name | product_type | sale_price | purchase_price | regist_date |
+------------+--------------+--------------+------------+----------------+-------------+
| 0001 | T恤衫 | 衣服 | 1000 | 500 | 2009-09-20 |
| 0002 | 打孔器 | 办公用品 | 500 | 320 | 2009-09-11 |
| 0003 | 运动T恤 | 衣服 | 4000 | 2800 | NULL |
| 0004 | 菜刀 | 厨房用具 | 3000 | 2800 | 2009-09-20 |
| 0005 | 高压锅 | 厨房用具 | 6800 | 5000 | 2009-01-15 |
| 0006 | 叉子 | 厨房用具 | 500 | NULL | 2009-09-20 |
| 0007 | 擦菜板 | 厨房用具 | 880 | 790 | 2008-04-28 |
| 0008 | 圆珠笔 | 办公用品 | 100 | NULL | 2009-11-11 |
+------------+--------------+--------------+------------+----------------+-------------+
8 rows in set (0.00 sec)
1. 编写一条SQL语句,从product(商品)表中选取出“登记日期(regist在2009年4月28日之后”的商品,查询结果要包含product name和regist_date两列。
SELECT product_name, regist_date
FROM product
WHERE regist_date > '2009-04-28';
查询结果:
+--------------+-------------+
| product_name | regist_date |
+--------------+-------------+
| T恤衫 | 2009-09-20 |
| 打孔器 | 2009-09-11 |
| 菜刀 | 2009-09-20 |
| 叉子 | 2009-09-20 |
| 圆珠笔 | 2009-11-11 |
+--------------+-------------+
5 rows in set (0.00 sec)
2. 请说出对product 表执行如下3条SELECT语句时的返回结果。
SELECT *
FROM product
WHERE purchase_price = NULL;
说明:返回空,= NULL会被判断为UNKNOWN,故返回为空;正确查询方式应为 IS NULL。
SELECT *
FROM product
WHERE purchase_price <> NULL;
说明:返回空,<> NULL会被判断为UNKNOWN,故返回为空;正确查询方式应为 IS NOT NULL。
SELECT *
FROM product
WHERE product_name > NULL;
说明:返回空,> NULL会被判断为UNKNOWN,故返回为空。
综上:
-- 以下的式子都会被判为UNKNOWN
= NULL
> NULL
< NULL
<> NULL
NULL = NULL
3. 示例代码清单中的SELECT语句能够从product表中取出“销售单价(saleprice)比进货单价(purchase price)高出500日元以上”的商品。请写出两条可以得到相同结果的SELECT语句。
示例代码和执行结果如下所示:
SELECT product_name,sale_price,purchase_price
FROM product
WHERE sale_price-purchase_price >= 500;
product_name | sale_price | purchase_price
-------------+------------+------------
T恤衫 | 1000 | 500
运动T恤 | 4000 | 2800
高压锅 | 6800 | 5000
可以得到相同结果的SELECT语句:
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 - 500 >= purchase_price;
4. 请写出一条SELECT语句,从product表中选取出满足“销售单价打九折之后利润高于100日元的办公用品和厨房用具”条件的记录。查询结果要包括product_name列、product_type列以及销售单价打九折之后的利润(别名设定为profit)。
提示:销售单价打九折,可以通过saleprice列的值乘以0.9获得,利润可以通过该值减去purchase_price列的值获得。
SELECT product_name, product_type, (sale_price * 0.9 - purchase_price) AS profit
FROM product
WHERE (product_type = '办公用品'
OR product_type = '厨房用具')
AND (sale_price * 0.9 - purchase_price) > 100;
查询结果:
+--------------+--------------+--------+
| product_name | product_type | profit |
+--------------+--------------+--------+
| 打孔器 | 办公用品 | 130.0 |
| 高压锅 | 厨房用具 | 1120.0 |
+--------------+--------------+--------+
2 rows in set (0.00 sec)
2.2.2 第二部分
1. 请指出下述SELECT语句中所有的语法错误
SELECT product id,SUM(product name)
--本SELECT语句中存在错误。
FROM product
GROUP BY product_type
WHERE regist_date > '2009-09-01';
说明:对分组数据进行筛选要用HAVING语句,而不是WHERE语句;WHERE语句在GROUPY BY之前,对行进行筛选
2. 请编写一条SELECT语句,求出销售单价(sale_price列)合计值是进货单价(purchase prilce列)合计值1.5倍的商品种类。执行结果如下所示
product_type | sum | sum
-------------+------+------
衣服 | 5000 | 3300
办公用品 | 600 | 320
SELECT product_type, SUM(sale_price), SUM(purchase_price)
FROM product
GROUP BY product_type
HAVING SUM(sale_price) >= SUM(purchase_price) * 1.5;
3. 此前我们曾经使用SELECT语句选取出了product(商品)表中的全部记录。当时我们使用了ORDERBY子句来指定排列顺序,但现在已经无法记起当时如何指定的了。请根据下列执行结果,思考ORDERBY子句的内容。
+------------+--------------+--------------+------------+----------------+-------------+
| product_id | product_name | product_type | sale_price | purchase_price | regist_date |
+------------+--------------+--------------+------------+----------------+-------------+
| 0003 | 运动T恤 | 衣服 | 4000 | 2800 | NULL |
| 0008 | 圆珠笔 | 办公用品 | 100 | NULL | 2009-11-11 |
| 0006 | 叉子 | 厨房用具 | 500 | NULL | 2009-09-20 |
| 0001 | T恤衫 | 衣服 | 1000 | 500 | 2009-09-20 |
| 0004 | 菜刀 | 厨房用具 | 3000 | 2800 | 2009-09-20 |
| 0002 | 打孔器 | 办公用品 | 500 | 320 | 2009-09-11 |
| 0005 | 高压锅 | 厨房用具 | 6800 | 5000 | 2009-01-15 |
| 0007 | 擦菜板 | 厨房用具 | 880 | 790 | 2008-04-28 |
+------------+--------------+--------------+------------+----------------+-------------+
8 rows in set (0.00 sec)
观察结果,发现regist_date是降序排列,尝试ORDER BY regist_date,代码和结果如下:
SELECT *
FROM product
ORDER BY regist_date DESC;
结果发现有2个问题:
1)regist_date为NULL对应的行被排序到了最后
2)regist_date = ‘2009-09-20’对应的3条数据顺序不对
观察最终的要求结果,是在regist_data降序排列之后,再对sale_price升序排序;因此可以解决问题2),调整后代码和结果如下:
SELECT *
FROM product
ORDER BY regist_date DESC, sale_price;
最后需要解决问题1) regist_date为NULL的排序,这里借助ISNULL()函数判断regist_date得到中间数据。
当regist_date为NULL时,ISNULL(regist_date)返回为1;当regist_date不为NULL时,ISNULL(regist_date)返回为0。
再利用ODER BY对ISNULL(regist_date)进行降序排序,即可解决问题2,对应代码如下:
SELECT *
FROM product
ORDER BY ISNULL(regist_date) DESC, regist_date DESC, sale_price;