SQL学习笔记04

Task 05 集合运算


Content

  • 表的加减法
  • 连结(JOIN)
  • 练习

Reference:
[1]GitHub - datawhalechina/wonderful-sql: Follow me,从 0 到 1 掌握 SQL,决胜秋招。

1. 表的加减法

1.1 集合运算符

在标准 SQL 中, 可以分别对<表、检索结果>使用:

  1. UNION — 并
  2. INTERSECT — 交
  3. EXCEPT — 差
    但MySQL截止至8.0,只支持UNION语句
    该文氏图展示了几种集合的基本运算.png
1.2 UNION
-- 示例1
SELECT product_id, product_name
FROM product
UNION
SELECT product_id, product_name
FROM product2;

-- 示例2
 SELECT product_id,product_name,product_type,sale_price,purchase_price
FROM product
WHERE sale_price<800
UNION
SELECT product_id,product_name,product_type,sale_price,purchase_price
FROM product
WHERE sale_price>1.5*purchase_price;

相关说明

  • UNION 等集合运算符通常都会除去重复的记录,若想保留,改为UNION ALL即可
  • UNION不仅可以对不同的两张表进行求并集运算. 对于同一张表, 也可以进行求并集的,相当于作为一个表的附加筛选条件,与WHERE+OR的效果类似
  • 但WHERE+OR无法合并两张表的查询结果,UNION可以
  • 有时候用UNION更直观,查询效率更高
  • 有时候, 即使数据类型不完全相同, 也会通过隐式类型转换来将两个类型不同的列放在一列里显示(时间日期类型和字符串, 数值以及缺失值均能兼容)
-- 示例3
SELECT SYSDATE(), SYSDATE(), SYSDATE()
UNION
SELECT ’chars’, 123, null;
1.3 INTERSECT
  • 对于同一个表的两个查询结果而言, 他们的交 INTERSECT 实际上可以等价地将两个查询的检索条件用AND 谓词连接来实现。
  • 对于两张表的交INTERSECT,在 MySQL 8.0 里无法直接得到
1.4 EXCEPT
  • MySQL 8.0 还不支持表的减法运算符 EXCEPT
  • 但是NOT IN 谓词, 我们同样可以实现表的减法,其效果和 SQL 标准语法中的EXCEPT 运算相同
1.5 对称差
  • 两个集合 A,B 的对称差是指那些仅属于 A 或仅属于 B 的元素构成的集合
    • 从直观上就能看出来, 两个集合的对称差等于 A-B 并上 B-A
    • 抑或可以理解为A与B的UNION减去INTERSECT
  • 同样,两个集合的交INTERSECT可以看作是两个集合的并UNION去掉两个集合的对称差


    总而言之围绕Venn图.png

2. 连结(JOIN)

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

  • 集合运算的特征是以行方向为单位进行操作
  • 使用关联子查询也可以从其他表获取信息, 但 连结 更适合从多张表获取信息
2.1 交叉连结/笛卡尔积(CROSS JOIN)
-- 示例1
SELECT SP.*, P.*
FROM shopproduct AS SP
CROSS JOIN product AS P;

-- 示例2
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;

相关说明

  • 在横向上对表进行扩张, 即增加新的列,但没有了 ON 子句的限制, 会对左表和右表的每一行进行组合, 这经常会导致很多无意义的行出现在检索结果中
  • 交叉连结是对两张表中的全部记录进行交叉组合, 因此结果中的记录数通常是两张表中行数的乘积
  • 交叉连结没有应用到实际业务之中的原因有两个。一是其结果没有实用价值, 二是由于其结果行数太多, 需要花费大量的运算时间和高性能设备的支持。
  • 但是交叉连结可以用来快速产生非常大的(无意义的)表,可以给面试官露一手(bushi
  • 内连结是交叉连结的一部分,“内”也可以理解为“包含在交叉连结结果中的部分”. 相反, 外连结的“外”可以理解为“交叉连结结果之外的部分”
2.2 内连接(INNER JOIN)
-- 示例1
SELECT 
  SP.shop_id,SP.shop_name,SP.product_id,
  P.product_name,P.product_type,P.sale_price,SP.quantity
FROM
  shopproduct AS SP
INNER JOIN 
  product AS P
ON SP.product_id = P.product_id;    #指定连结条件

相关说明

  • 进行连结时需要在 FROM 子句中使用多张表
  • 必须使用 ON 子句来指定连结条件
  • SELECT 子句中的列最好按照表名. 列名的格式来使用
2.2.1 结合 WHERE 子句使用内连结
SELECT 
  SP.shop_id,SP.shop_name,SP.product_id,
  P.product_name,P.product_type,P.sale_price,SP.quantity
FROM
  shopproduct AS SP
INNER JOIN
  product AS P
ON SP.product_id = P.product_id
WHERE 
  SP.shop_name = ’东京’
AND 
  P.product_type = ’衣服’ ;
  • WHERE 子句将在 FROM 子句之后执行, 也就是说, 在做完 INNER JOIN ... ON得到一个新表后, 才会执行 WHERE 子句
  • 查询的执行顺序: FROM 子句->WHERE 子句->SELECT 子句
  • 还可以将 WHERE 子句中的条件直接添加在 ON 子句中, 这时候 ON 子句后最好用括号将连结条件和筛选条件括起来,但这样子不太方便阅读,一般不建议
  • 或者先分别在两张表里做筛选, 把复杂的筛选条件按表分拆, 然后把筛选结果 (作为表) 连接起来
-- 示例
SELECT SP.shop_id
- ,SP.shop_name
- ,SP.product_id
- ,P.product_name
- ,P.product_type
- ,P.sale_price
- ,SP.quantity
- FROM (-- 子查询 1:从shopproduct 表筛选出东京商店的信息
- SELECT *
- FROMshopproduct
- WHERE shop_name = ’东京’ ) AS SP
- INNER JOIN -- 子查询 2:从 product 表筛选出衣服类商品的信息
- (SELECT *
- FROMproduct
- WHERE product_type = ’衣服’) AS P
- ON SP.product_id = P.product_id;
2.2.2 结合 GROUP BY 子句使用内连结
-- 示例
SELECT SP.shop_id
- ,SP.shop_name
- ,MAX(P.sale_price) AS max_price
- FROM shop product AS SP
- INNER JOIN product AS P
- ON SP.product_id = P.product_id
- GROUP BY SP.shop_id,SP.shop_name

相关说明

  • 结合 GROUP BY 子句使用内连结, 需要根据分组列位于哪个表区别对待
2.2.3 内连结与关联子查询
-- 示例
 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.2.4 自然连结 (NATURAL JOIN)
  • 当两个表进行自然连结时, 会按照两个表中都包含的列名来进行等值内连结, 此时无需使用 ON 来指定连接条件
  • 把两个表的公共列 (可以有多个公共列) 放在第一列, 然后按照两个表的顺序和表中列的顺序, 将两个表中的其他列都罗列出来
2.3 外连接(OUTER JOIN)
  • 内连结是交叉连结的一部分,“内”也可以理解为“包含在交叉连结结果中的部分”. 相反, 外连结的“外”可以理解为“交叉连结结果之外的部分”
  • 外连结会根据外连结的种类有选择地保留无法匹配到的行。
  • 按照保留的行位于哪张表, 外连结有三种形式: 左连结, 右连结和全外连结。
-- 左连结
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)>
  • 选取出单张表中全部的信息:对于外连结来说, 只要数据存在于某一张表当中, 就能够读取出来. 在实际的业务中, 例如想要生成固定行数的单据时, 就需要使用外连结
  • 使用 LEFT、RIGHT 来指定主表:顾名思义, 使用 LEFT 时 FROM 子句中写在左侧的表是主表, 使用 RIGHT 时右侧的表是主表,通过交换两个表的顺序, 同时将 LEFT 更换为 RIGHT(如果原先是 RIGHT, 则更换为 LEFT), 两种方式会到完全相同的结果。

3. 练习

  1. 找出 product 和 product2 中售价高于 500 的商品的基本信息
SELECT * FROM product
 WHERE sale_price>500
UNION # UNION ALL才是不删除重复行
SELECT * FROM product2
 WHERE sale_price>500;
  1. 借助对称差的实现方式, 求 product 和 product2 的交集
-- 方法一:最直观
SELECT * FROM product 
WHERE product_id in (SELECT product_id FROM product2)

-- 方法二:A+B-[(A-B)+(B-A)]
SELECT * FROM 
(SELECT * FROM product UNION SELECT * FROM product2) 
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)); 
  1. 每类商品中售价最高的商品都在哪些商店有售?
SELECT SP.shop_id, SP.shop_name, P.product_id, P.product_name, p.product_type
FROM shopproduct AS SP
INNER JOIN 
(SELECT product_id, product_name,product_type, MAX(sale_price) FROM product
GROUP BY product_type) AS P
ON SP.product_id = P.product_id;
  1. 分别使用内连结和关联子查询每一类商品中售价最高的商品
-- 内连结
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 MP
WHERE P.product_id=MP.product_id
GROUP BY product_type);
  1. 用关联子查询实现:在 product 表中,取出 product_id,product_name, sale_price, 并按照商品的售价从低到高进行排序、对售价进行累计求和
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 205,386评论 6 479
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,939评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,851评论 0 341
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,953评论 1 278
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,971评论 5 369
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,784评论 1 283
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,126评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,765评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 43,148评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,744评论 2 323
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,858评论 1 333
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,479评论 4 322
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,080评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,053评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,278评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,245评论 2 352
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,590评论 2 343

推荐阅读更多精彩内容

  • 1.表的加减法 集合在数据库领域表示记录的集合.具体来说,表、视图和查询的执行结果都是记录的集合, 其中的元素为表...
    penta_ever阅读 485评论 0 0
  • 4.1 表的加减法 4.1.1 什么是集合运算 集合在数学领域表示“各种各样的事物的总和”, 在数据库领域表示记录...
    忘原_b2d5阅读 666评论 0 0
  • 4.1表的加法--UNION SELECT product_id, product_name FROM prod...
    6aeac1306687阅读 357评论 0 0
  • (1) 选择最有效率的表名顺序(只在基于规则的优化器中有效): ORACLE 的解析器按照从右到左的顺序处理FRO...
    雅式创始人阅读 3,215评论 2 46
  • oracle基本运算符 between ....and .... 运算符,取一个区间的值,仅限一个条件中 orac...
    一格命MrLixinyu阅读 492评论 0 3