二、为什么要进行表连接join?
在数据库设计中,如果涉及到较多的业务表,为了防止相同数据在多个表中同时存放,减少数据冗余和存储浪费,通常会将不同的数据放在不同的表中,对数据进行拆解分别存储。
但在分析的过程中,为了获取完整的分析数据,我们就需要从多表中取数据,将多个表连接成一个表,方便我们进行分析。所以连接查询是SQL查询语句中最常见、运用最广泛的查询技巧。
根据表的连接方式划分,将表连接分为内连接、外连接,下图为连接方式的细分。
在进行实际案例演示之前,我们先对各种连接的原理和使用场景做个介绍。
三、内连接INNER JOIN
内连接inner join使用连接运算符匹配两个表共有的列,返回两个表中均满足连接条件的记录,若不满足条件则不返回。
内连接按照连接方式的不同,又可以分为以下几种:
等值连接:在连接条件中使用等号(=)运算符连接两个表中相同的列,返回两个表共同满足连接条件的所有行。
非等值连接:在连接条件使用除等于运算符以外的其它比较运算符进行连接的情况,包括>、>=、<=、<、!>、!<和<>,均为非等值连接。
自连接:有时在查询时需要自身和自身连接(自连接),这个时候我们要为同一个表定义不同的别名以示区分。
笛卡尔积连接:两张表中的每一条记录和另外一个表进行笛卡尔积组合,然后根据WHERE条件过滤结果集中的记录。
在所有的内连接类型中最典型、最常用的内连接方式是等值连接,也就是连接条件ON中的匹配类型为等值“=”匹配,等值连接返回两个表中共同字段值相等的所有行。
如下图所示,表A和B进行等值连接后,返回的是两个表中满足连接条件的共用部分C,即交集。
还是通过之前产品销售案例说明,我们有一张产品销售表product记录了用户产品的销售信息,产品维表dim_product记录了产品的供应商信息,如果表A、B按照product_id列进行等值连接,连接过程和结果如下所示。
下面我们通过实际的代码进行说明。
产品销售表product表我们之前已经构建,如果不清楚表结构和数据的可以翻看上一篇文章,这里我们需要构建一个记录产品供应商信息的产品维表dim_product。
--1、 在数据库Sales创建表,用于存放演示的数据USE Sales;
-- 2、创建产品维表dim_productCREATE TABLE dim_product( product_id CHAR(4) NOT NULL,-- 产品id,字符类型CHAR supplier VARCHAR(100) NOT NULL,-- 产品供应商,字符类型VARCHAR production_date DATE -- 产品生产日期,日期类型DATE);
-- 3、插入一些用于演示的数据,只是用来演示说明,并无实际意义和真实性。INSERT INTO dim_product VALUES ('0001','sup_A','2021-03-01');INSERT INTO dim_product VALUES ('0003', 'sup_A', '2021-04-01');INSERT INTO dim_product VALUES ('0004', 'sup_B', '2021-05-01');INSERT INTO dim_product VALUES ('0010', 'sup_C', '2021-06-01');
创建完dim_product后,我们完成产品销售表product和产品维表dim_product的等值连接,皆可获得各产品的供应商信息,代码和结果如下:
-- 通过product_id进行等值连接selectA.product_id AS A_product_id,A.sale_date,B.product_id AS B_product_id,B.supplierfrom product Ainner join dim_product Bon A.product_id = B.product_id;
结果如下:结果中并没有出现product_id为0002和0010的记录
四、外连接Left/Right/Full Join
除了内连接以外,在实际的工作中,即使是在连接条件不满足的情况下,我们也希望能够返回结果,这个时候就要用到外连接。
常见的外连接主要有左、右、全连接,区别如下:
1、左/右连接:LEFT/RIGHT JOIN
左连接left join或left outer join 对左表不加限制,结果返回左表的所有行,如果左表的某行在右表中没有匹配行,则在相关联的结果集行中右表的所有选择列表列均为空值。
如下图所示,以表A为左表,和B进行左连接后,返回的是左表的所有行,如果B表中没有满足连接条件的,将B表中的各列置为空值。
相对地,对于右连接,right join 或right outer join 对右表不加限制,结果返回右表的所有行,如果右表的某行在左表中没有匹配行,则在相关联的结果集行中左表的所有选择列表列均为空值,示意如下:
左连接和右连接是相对的,一般来说,我们在使用中主要用左连接,所以接下来主要以左连接为例进行说明。
还是通过之前产品销售案例说明,我们用产品销售表product作为左表,和产品维表dim_product按照product_id列进行左连接,连接过程和结果如下所示。
下面我们通过实际的代码进行说明。
-- 通过product_id进行左连接selectA.product_id AS A_product_id,A.sale_date,B.product_id AS B_product_id,B.supplierfrom product Aleft join dim_product Bon A.product_id = B.product_id;
结果如下:A表中product_id为0002的记录仍然返回。
2、全连接 FULL JOIN
除了上述内连接、左右连接外,有时候我们想把两个表中所有的记录都返回,这时就需要用到全连接 full join 或者full outer join。
全连接full join对左、右表均不加限制,连接返回左表和右表中的所有行。如果表之间有匹配行,则返回共同的匹配行,当某行在另一个表中没有匹配行时,则另一个表的选择列表列置为空值。
如下图所示,表A和表B进行全连接后,返回的是两表中的所有行,即A、B表的并集。
还是通过之前产品销售案例说明,我们用产品销售表product作为左表,和产品维表dim_product按照product_id列进行左连接,连接过程和结果如下所示。