本专栏与大家分享小白学SQL的全过程,记录学习中遇到的难题与相应解决方法,希望能和大家共勉成长。才疏学浅文章多有错漏,还望大家多多指导,谢谢!
资料来源:DataWhale组队学习
结合运算并,交和差-UNION,INTERSECT和EXCEPT
表的加法—UNION
**练习题:**假设连锁店想要增加毛利率超过 50%或者售价低于 800 的货物的存货量, 请使用 UNION 对分别满足上述两个条件的商品的查询结果求并集.
练习题:
找出 product 和 product2 中售价高于 500 的商品的基本信息.
Error Code: 1052. Column 'sale_price' in where clause is ambiguous
不去重 UNION ALL
练习题:
商店决定对product表中利润低于50%和售价低于1000的商品提价, 请使用UNION ALL 语句将分别满足上述两个条件的结果取并集. 查询结果类似下表:
bag模型bag 里面允许存在重复元素, 如果同一个元素被加入多次, 则袋子里就有多个该元素.
UNION ALL, EXCEPT ALL 都是按出现次数进行减法, 使用bag模型进行运算.
对于两个 bag, 他们的并运算会按照:1.该元素是否至少在一个 bag 里出现过, 2.该元素在两个 bag 中的最大出现次数这两个方面来进行计算. 因此对于 A = {1,1,1,2,3,5,7}, B = {1,1,2,2,4,6,8} 两个 bag, 它们的并就等于 {1,1,1,2,2,3,4,5,6,7,8}.
对于两个 bag, 他们的交运算会按照:1.该元素是否同时属于两个 bag, 2.该元素在两个 bag 中的最小出现次数这两个方面来进行计算. 因此对于 A = {1,1,1,2,3,5,7}, B = {1,1,2,2,4,6,8} 两个 bag, 它们的交运算结果就等于 {1,1,2}.
对于两个 bag, 他们的差运算会按照:1.该元素是否属于作为被减数的 bag,2.该元素在两个 bag 中的出现次数,对于 A = {1,1,1,2,3,5,7}, B = {1,1,2,2,4,6,8} 两个 bag, 它们的差就等于 {1,3,5,7}.
隐式类型转换来将两个类型不同的列放在一列里显示, 例如字符串和数值类型:
SELECT product_id, product_name, '1'
FROM product
UNION
SELECT product_id, product_name,sale_price
FROM product2;
练习题:
使用 SYSDATE()函数可以返回当前日期时间, 是一个日期时间类型的数据, 试测试该数据类型和数值,字符串等类型的兼容性.
Error 1064语法错误:
截止到 MySQL 8.0 版本, MySQL 仍然不支持 INTERSECT 操作.
MySQL 8.0 还不支持 表的减法运算符 EXCEPT. 不过, 借助第六章学过的NOT IN 谓词, 我们同样可以实现表的减法.
练习题**:**
找出只存在于product表但不存在于product2表的商品.
-- 使用 IN 子句的实现方法
SELECT *
FROM product
WHERE product_id NOT IN (SELECT product_id
FROM product2)
练习题:
使用NOT谓词进行集合的减法运算, 求出product表中, 售价高于2000,但利润低于30%的商品, 结果应该如下表所示.
SELECT*
FROMproduct
WHEREsale_price >2000ANDproduct_idNOTIN(SELECTproduct_id
FROMproduct
WHEREsale_price>1.3*purchase_price);
练习题:
****使用AND谓词查找product表中利润率高于50%,并且售价低于1500的商品,查询结果如下所示.
对称差两个集合A,B的对称差是指那些仅属于A或仅属于B的元素构成的集合
连结(join)集合运算的特征就是以行方向为单位进行操作,会导致记录行数的增减
使用函数或者 CASE表达式等列运算, 可以增加列的数量, 但仍然只能从一张表中获得一些"引申列", 本质并不能提供更多的信息.
期望得到的数据往往会分散在不同的表之中, 这时候就需要使用连结了
使用关联子查询也可以从其他表获取信息, 但连结更适合从多张表获取信息.
内连结(INNER JOIN)
内连结的语法格式是:
-- 内连结
FROM INNER JOIN ON
找出一个类似于"轴"或者"桥梁"的公共列, 将两张表用这个列连结起来. 这就是连结运算所要作的事情.
子查询结果是虚拟的表,因此INNER JOIN可接子查询分解任务
结合 GROUP BY 子句使用内连结, 需要根据分组列位于哪个表区别对待
最简单是在内连结之前就使用 GROUP BY 子句
如果分组列和被聚合的列不在同一张表, 且二者都未被用于连结两张表, 则只能先连结, 再聚合
在实践中, 一定要按照易于让自己理解的思路去分层次写代码, 而不要花费很长世间写出一个效率可能更高但自己和他人理解起来难度更高的代码
自然连结并不是区别于内连结和外连结的第三种连结, 它其实是内连结的一种特例–当两个表进行自然连结时, 会按照两个表中都包含的列名来进行等值内连结, 此时无需使用 ON 来指定连接条件.
使用自然连结还可以求出两张表或子查询的公共部分
SELECT*FROMproductNATURALJOINproduct2
在自然连结进行行数据比较时, 实际上是在逐字段进行等值连结“=”, 两个缺失值用等号进行比较, 结果不为真. 而连结只会返回对连结条件返回为真的那些行。
如果我们将查询语句进行修改:
SELECT *
FROM (SELECT product_id, product_name
FROM product ) AS A
NATURAL JOIN
(SELECT product_id, product_name
FROM product2) AS B;
外连结
内连结会丢弃两张表中不满足 ON 条件的行,和内连结相对的就是外连结. 外连结会根据外连结的种类有选择地保留无法匹配到的行.
按照保留的行位于哪张表,外连结有三种形式: 左连结, 右连结和全外连结
左连结会保存左表中无法按照 ON 子句匹配到的行, 此时对应右表的行均为缺失值; 右连结则会保存右表中无法按照 ON 子句匹配到的行, 此时对应左表的行均为缺失值; 而全外连结则会同时保存两个表中无法按照 ON子句匹配到的行, 相应的另一张表中的行用缺失值填充.
三种外连结的对应语法分别为:
-- 左连结
FROM LEFT OUTER JOIN ON
-- 右连结
FROM RIGHT OUTER JOIN ON
-- 全外连结
FROM FULL OUTER JOIN ON