SQL集合运算

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

练习题 :分别使用 UNION 或者 OR 谓词,找出毛利率不足 30%或毛利率未知的商品.
– 使用 OR 谓词
select product_name from product
where sale_price / purchase_price is null
or sale_price < 1.3 * purchase_price;
– 使用 UNION
select product_name from product
where sale_price / purchase_price is null
union
select product_name from product
where sale_price < 1.3 * purchase_price;

练习题:找出 product 和 product2 中售价高于 500 的商品的基本信息.
select * from product
where sale_price > 500
union
select * from product2
where sale_price > 500;
练习题:商店决定对product表中利润低于50%和售价低于1000的商品提价, 请使用UNION ALL 语句将分别满足上述两个条件的结果取并集.
1.1差集,补集与表的减法
求集合差集的减法运算和实数的减法运算有些不同, 当使用一个集合A减去另一个集合B的时候,对于只存在于集合B而不存在于集合A的元素, 采取直接忽略的策略,因此集合A和B做减法只是将集合A中也同时属于集合B的元素减掉.练习题:使用 SYSDATE()函数可以返回当前日期时间, 是一个日期时间类型的数据, 试测试该数据类型和数值,字符串等类型的兼容性.
例如, 以下代码可以正确执行, 说5 对称差
两个集合A,B的对称差是指那些仅属于A或仅属于B的元素构成的集合. 对称差也是个非常基础的运算, 例如, 两个集合的交就可以看作是两个集合的并去掉两个集合的对称差.上述方法在其他数据库里也可以用来简单地实现表或查询结果的对称差运算: 首先使用UNION求两个表的并集, 然后使用INTERSECT求两个表的交集, 然后用并集减去交集, 就得到了对称差.明时间日期类型和字符串,数值以及缺失值均能兼容.
SELECT SYSDATE(), SYSDATE(), SYSDATE()
UNION
SELECT ‘chars’, 123, null;
1.2 对称差
两个集合A,B的对称差是指那些仅属于A或仅属于B的元素构成的集合. 对称差也是个非常基础的运算, 例如, 两个集合的交就可以看作是两个集合的并去掉两个集合的对称差.上述方法在其他数据库里也可以用来简单地实现表或查询结果的对称差运算: 首先使用UNION求两个表的并集, 然后使用INTERSECT求两个表的交集, 然后用并集减去交集, 就得到了对称差.

  1. 连结 (JOIN)
    前一节我们学习了 UNION和INTERSECT 等集合运算, 这些集合运算的特征就是以行方向为单位进行操作. 通俗地说, 就是进行这些集合运算时, 会导致记录行数的增减. 使用 UNION 会增加记录行数,而使用 INTERSECT 或者 EXCEPT 会减少记录行数.
    2.1结合 WHERE 子句使用内连结
    如果需要在使用内连结的时候同时使用 WHERE 子句对检索结果进行筛选, 则需要把 WHERE 子句写在 ON 子句的后边.
    2.2结合 GROUP BY 子句使用内连结
    结合 GROUP BY 子句使用内连结, 需要根据分组列位于哪个表区别对待.最简单的情形, 是在内连结之前就使用 GROUP BY 子句.但是如果分组列和被聚合的列不在同一张表, 且二者都未被用于连结两张表, 则只能先连结, 再聚合.
    2.3自连结(SELF JOIN)
    之前的内连结, 连结的都是不一样的两个表. 但实际上一张表也可以与自身作连结, 这种连接称之为自连结. 需要注意, 自连结并不是区分于内连结和外连结的第三种连结, 自连结可以是外连结也可以是内连结, 它是不同于内连结外连结的另一个连结的分类方法.
    2.4内连结与关联子查询
    回忆一下关联子查询中的问题:找出每个商品种类当中售价高于该类商品的平均售价的商品。当时我们是使用关联子查询来实现的。

SELECT product_type, product_name, sale_price
FROM product AS P1
WHERE sale_price > (SELECT AVG(sale_price)
FROM product AS P2
WHERE P1.product_type = P2.product_type
GROUP BY product_type);
使用内连结同样可以解决这个问题:
首先, 使用 GROUP BY 按商品类别分类计算每类商品的平均价格.

SELECT product_type
,AVG(sale_price) AS avg_price
FROM product
GROUP BY product_type;
接下来, 将上述查询与表 product 按照 product_type (商品种类)进行内连结.

SELECT P1.product_id
,P1.product_name
,P1.product_type
,P1.sale_price
,P2.avg_price
FROM product AS P1
INNER JOIN
(SELECT product_type,AVG(sale_price) AS avg_price
FROM product
GROUP BY product_type) AS P2
ON P1.product_type = P2.product_type;
最后, 增加 WHERE 子句, 找出那些售价高于该类商品平均价格的商品.完整的代码如下:

SELECT P1.product_id
,P1.product_name
,P1.product_type
,P1.sale_price
,P2.avg_price
FROM product AS P1
INNER JOIN
(SELECT product_type,AVG(sale_price) AS avg_price
FROM product
GROUP BY product_type) AS P2
ON P1.product_type = P2.product_type
WHERE P1.sale_price > P2.avg_price;
仅仅从代码量上来看, 上述方法似乎比关联子查询更加复杂, 但这并不意味着这些代码更难理解. 通过上述分析, 很容易发现上述代码的逻辑实际上更符合我们的思路, 因此尽管看起来复杂, 但思路实际上更加清晰.
2.5自然连结(NATURAL JOIN)
自然连结并不是区别于内连结和外连结的第三种连结, 它其实是内连结的一种特例–当两个表进行自然连结时, 会按照两个表中都包含的列名来进行等值内连结, 此时无需使用 ON 来指定连接条件.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值