0
点赞
收藏
分享

微信扫一扫

MySQL学习(四)集合运算&练习题

phpworkerman 2022-03-23 阅读 73

集合在数学领域表示“各种各样的事物的总和”, 在数据库领域表示记录的集合. 具体来说,表、视图和查询的执行结果都是记录的集合, 其中的元素为表或者查询结果中的每一行。
在标准 SQL 中, 分别对检索结果使用 UNION, INTERSECT, EXCEPT 来将检索结果进行并,交和差运算, 像UNION,INTERSECT, EXCEPT这种用来进行集合运算的运算符称为集合运算符。
在这里插入图片描述

集合运算符的使用

  • 表的并集–UNION
    用法:
SELECT product_id, product_name
  FROM product
 UNION
SELECT product_id, product_name
  FROM product2;

需注意点是 UNION 等集合运算符通常都会除去重复的记录,需要包含重复行,只需要在 UNION 后面添加 ALL 关键字就可以了。
UNION 与 OR 谓词区别:对于同一个表的两个不同的筛选结果集, 使用UNION 对两个结果集取并集, 和把两个子查询的筛选条件用 OR 谓词连接,会得到相同的结果, 但倘若要将两个不同的表中的结果合并在一起,就不得不使用 UNION 了。而且, 即便是对于同一张表, 有时也会出于查询效率方面的因素来使用 UNION。

  • 表的交集–INTERSECT
    遗憾的是,MySQL 8.0 不支持交运算INTERSECT,需要用 inner join 来求得交集。
SELECT p1.product_id, p1.product_name
 FROM Product p1
INNER JOIN Product2 p2
ON p1.product_id=p2.product_id

对于同一个表的两个查询结果而言, 他们的交INTERSECT实际上可以等价地将两个查询的检索条件用AND谓词连接来实现。

SELECT * 
  FROM Product
 WHERE sale_price > 1.5 * purchase_price 
   AND sale_price < 1500
  • 表的差集–EXCEPT
    同样,MySQL 8.0 还不支持表的减法运算符 EXCEPT,但可以借用NOT IN 谓词实现
SELECT * 
  FROM Product
 WHERE product_id NOT IN (SELECT product_id 
                            FROM Product2)
  • 对称差
    两个集合A,B的对称差是指那些仅属于A或仅属于B的元素构成的集合
-- 使用 NOT IN 实现两个表的差集
SELECT * 
 FROM Product
WHERE product_id NOT IN (SELECT product_id FROM Product2)
UNION
SELECT * 
 FROM Product2
WHERE product_id NOT IN (SELECT product_id FROM Product)

连结(JOIN)

连结(JOIN)就是使用某种关联条件(一般是使用相等判断谓词"="), 将其他表中的列添加过来, 进行“添加列”的集合运算.

  • 内连结(INNER JOIN)
    -- 内连结语法 FROM <tb_1> INNER JOIN <tb_2> ON <condition(s)>
  • 自连结(SELF JOIN)
    之前的内连结, 连结的都是不一样的两个表。但实际上一张表也可以与自身作连结, 这种连接称之为自连结.
  • 外连结(OUTER JOIN)
    内连结会丢弃两张表中不满足 ON 条件的行,和内连结相对的就是外连结. 外连结会根据外连结的种类有选择地保留无法匹配到的行。
    按照保留的行位于哪张表,外连结有三种形式: 左连结, 右连结和全外连结。左连结会保存左表中无法按照 ON 子句匹配到的行, 此时对应右表的行均为缺失值; 右连结则会保存右表中无法按照 ON 子句匹配到的行, 此时对应左表的行均为缺失值; 而全外连结则会同时保存两个表中无法按照 ON子句匹配到的行, 相应的另一张表中的行用缺失值填充。
-- 左连结     
FROM <tb_1> LEFT  OUTER JOIN <tb_2> ON <condition(s)>

-- 右连结     
FROM <tb_1> RIGHT OUTER JOIN <tb_2> ON <condition(s)>

-- 全外连结
FROM <tb_1> FULL  OUTER JOIN <tb_2> ON <condition(s)>
  • 多表连结
    通常连结只涉及 2 张表,但有时也会出现必须同时连结 3 张以上的表的情况, 原则上连结表的数量并没有限制。
  • ON 子句进阶–非等值连结
    使用比较运算符来进行连接,包括比较运算符(<,<=,>,>=, BETWEEN)和谓词运算(LIKE, IN, NOT 等等)在内的所有的逻辑运算都可以放在 ON 子句内作为连结条件。
  • 交叉连结—— CROSS JOIN(笛卡尔积)
    在连结去掉 ON 子句, 就是所谓的交叉连结(CROSS JOIN), 交叉连结又叫笛卡尔积。
-- 1.使用关键字 CROSS JOIN 显式地进行交叉连结
SELECT SP.shop_id
       ,SP.shop_name
       ,SP.product_id
       ,P.product_name
       ,P.sale_price
  FROM ShopProduct AS SP
 CROSS JOIN Product AS P;
--2.使用逗号分隔两个表,并省略 ON 子句
SELECT SP.shop_id
       ,SP.shop_name
       ,SP.product_id
       ,P.product_name
       ,P.sale_price
  FROM ShopProduct AS SP , Product AS P;

练习题

先建立习题所需要的的表product2,product同之前MySQL学习文章的。

CREATE TABLE product2
(product_id CHAR(4) NOT NULL,
product_name VARCHAR(100) NOT NULL,
product_type VARCHAR(32) NOT NULL,
sale_price INTEGER ,
purchase_price INTEGER ,
regist_date DATE ,
PRIMARY KEY (product_id));
INSERT INTO product2 VALUES('0001', 'T恤衫', '衣服', 1000, 500, '2009-09-20');
INSERT INTO product2 VALUES('0002', '打孔器', '办公用品', 500, 320, '2009-09-11');
INSERT INTO product2 VALUES('0003', '运动T恤', '衣服', 4000, 2800, NULL);
INSERT INTO product2 VALUES('0009', '手套', '衣服', 800, 500, NULL);
INSERT INTO product2 VALUES('0010', '水壶', '厨房用具', 2000, 1700, '2009-09-20');

在这里插入图片描述

4.1

找出 product 和 product2 中售价高于 500 的商品的基本信息。
答:

SELECT  *
  FROM Product 
 WHERE  sale_price > 500
 UNION ALL
SELECT *
  FROM Product2 
 WHERE  sale_price > 500;

在这里插入图片描述

4.2

借助对称差的实现方式, 求product和product2的交集。
答:

SELECT * FROM 
	(SELECT * FROM product 
		UNION 
	 SELECT * FROM product2) 
	as u
	WHERE product_id 
		NOT IN(SELECT product_id 
			FROM product 
			WHERE product_id 
			NOT IN 
			(SELECT product_id FROM product2)
			UNION
			SELECT product_id 
			FROM product2 
			WHERE product_id 
			NOT IN 
			(SELECT product_id FROM product)
			);

在这里插入图片描述

4.3

每类商品中售价最高的商品都在哪些商店有售 ?
答:
建立表shopproduct

CREATE TABLE shopproduct
(  shop_id CHAR(4)     NOT NULL,
 shop_name VARCHAR(200) NOT NULL,
product_id CHAR(4)      NOT NULL, 
quantity INTEGER      NOT NULL,
PRIMARY KEY (shop_id, product_id) -- 指定主键
);
-- DML :插入数据
START TRANSACTION; -- 开始事务
INSERT INTO shopproduct  VALUES ('000A', '东京', '0001', 30);
INSERT INTO shopproduct  VALUES ('000A', '东京', '0002', 50);
INSERT INTO shopproduct  VALUES ('000A', '东京', '0003', 15);
INSERT INTO shopproduct  VALUES ('000B', '名古屋', '0002', 30);
INSERT INTO shopproduct  VALUES ('000B', '名古屋', '0003', 120);
INSERT INTO shopproduct  VALUES ('000B', '名古屋', '0004', 20);
INSERT INTO shopproduct  VALUES ('000B', '名古屋', '0006', 10);
INSERT INTO shopproduct  VALUES ('000B', '名古屋', '0007', 40);
INSERT INTO shopproduct  VALUES ('000C', '大阪', '0003', 20);
INSERT INTO shopproduct  VALUES ('000C', '大阪', '0004', 50);
INSERT INTO shopproduct  VALUES ('000C', '大阪', '0006', 90);
INSERT INTO shopproduct  VALUES ('000C', '大阪', '0007', 70);
INSERT INTO shopproduct  VALUES ('000D', '福冈', '0001', 100);
COMMIT; -- 提交事务

在这里插入图片描述

SELECT sp.shop_id, sp. shop_name, sp.quantity,
        p.product_id, p. product_name, p. product_type, p. sale_price,
        mp.maxp AS '该类商品的最大售价' 
FROM product AS p 
INNER JOIN shopproduct AS sp 
ON sp.product_id = p.product_id
INNER JOIN (
			SELECT  product_type, MAX( sale_price) AS maxp FROM product 
            GROUP BY  product_type
            ) AS mp
ON mp. product_type = p. product_type AND p. sale_price = mp.maxp;

在这里插入图片描述

4.4

分别使用内连结和关联子查询每一类商品中售价最高的商品。
答:

--内连结
SELECT p.product_id, p. product_name, p. product_type, p. sale_price
FROM product AS p 
INNER JOIN(
			SELECT  product_type, MAX( sale_price) AS maxp FROM product 
            GROUP BY  product_type
            ) AS mp
ON mp. product_type = p. product_type AND p. sale_price = mp.maxp;

在这里插入图片描述

--关联子查询
SELECT p.product_id, p. product_name, p. product_type, p. sale_price 
FROM product AS p
WHERE  sale_price = (SELECT MAX( sale_price) 
					FROM product AS p1 
					WHERE p. product_type = p1. product_type
					GROUP BY  product_type);

在这里插入图片描述

4.5

用关联子查询实现:在 product 表中,取出 product_id, product_name, sale_price, 并按照商品的售价从低到高进行排序、对售价进行累计求和。
答:

SELECT p.product_id, p. product_name, p. product_type, p. sale_price,
	(SELECT SUM( sale_price) FROM product AS p1
	WHERE p. sale_price > p1. sale_price
	OR (p. sale_price = p1. sale_price AND p.product_id >= p1.product_id)
	) AS '累计求和'
FROM product AS p 
ORDER BY  sale_price;

在这里插入图片描述

举报

相关推荐

java集合练习题

[练习题]运算符

java集合练习题02

mysql查询练习题

MySql作业练习题

JAV练习题(Map双列集合)

0 条评论