一、分类 在多表关联查询时,常常要用到链接查询,SQL中链接分为四种:内链接(inner join或join)、左外链接(left outer join)、右外链接(right outer join)、全链接(full outer join); 其中,除了inner join其他三种都是外链接。 首先建2张表用于后面的讲解用。 表A:合同表mysql
CREATE TABLE `contract` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '合同表主键ID', `contract_name` varchar(255) DEFAULT NULL COMMENT '合同名称', `contract_no` varchar(200) DEFAULT NULL COMMENT '合同编号', `contract_amount` decimal(11,2) DEFAULT NULL COMMENT '合同金额', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=5 DEFAULT CHARSET=utf8;
表B:合同金额历史修改记录表sql
CREATE TABLE `contract_history` ( `id` int(10) unsigned NOT NULL AUTO_INCREMENT COMMENT '历史合同金额表主键ID', `fk_contract_id` int(10) NOT NULL COMMENT '合同ID', `hi_contract_amount` decimal(10,2) DEFAULT NULL COMMENT '合同历史金额', PRIMARY KEY (`id`) ) ENGINE=InnoDB AUTO_INCREMENT=4 DEFAULT CHARSET=utf8;
其中,B表中的fk_contract_id字段与A表中的id字段有外键关系;code
二、inner join内链接 内链接结果返回A、B两个表均匹配的数据集,其中有一个表的数据不知足,则那条数据不返回; 模拟数据以下: A:blog
B:ci
内链接查询:io
select * from contract a INNER JOIN contract_history b on a.id=b.fk_contract_id
结果:效率
分析:基础
一、A表中合同3的数据并无查询出来,由于B表中没有对应的记录; 二、合同1的数据查出2条了,由于B表中显示合同1修改过2次合同金额了,所以能够看出,当A、B表是一对多的关系时,因inner join没有主从表之分,所以只要A、B表按照链接条件可以匹配的数据都会返回,其中,“一对多”关系中的“一”表数据会有重复,所以使用时须要注意这一点! 三、内链接时,筛选条件放在链接条件on中和放在where中查询的结果集是一致的,可是效率上会有区别,通常来讲,放在on中效率更高一些。扩展
三、left outer join左外链接select
一般也简称为左链接,sql中可省略outer,写为:left join; 左链接以左表为主表,右表为从表,返回结果集以左表数据为基础,链接右表获取额外信息; 查询语句举例:
select * from contract a LEFT JOIN contract_history b on a.id=b.fk_contract_id
结果:
分析:
从结果能够看出,虽然合同3在B表中没有数据与之对应,可是仍是做为结果集中的一部分返回了,所以能够这么说,只要主表有N条记录,使用left join查询返回的结果集必定至少有N条记录(不考虑where条件)!
这里须要注意:若是A表与B表为一对多关系,查询结果记录数会大于主表(A表)记录数,例如上图中,合同1的记录就有2条;
特别注意左链接时查询条件放置的位置: 使用left join查询时,主表的筛选条件要放在where中,而从表的条件要看状况选择放在链接条件on中或是放在where中;下面举例子说明这两种状况: 栗子1:查询出全部历史合同金额有过300的合同记录。
sql:
SELECT * FROM contract a LEFT JOIN contract_history b ON a.id = b.fk_contract_id WHERE b.hi_contract_amount = 300
结果:
结果知足咱们的需求,可是若是把筛选条件放在on中:
SELECT * FROM contract a LEFT JOIN contract_history b ON a.id = b.fk_contract_id AND b.hi_contract_amount = 300
结果:
显然,查询结果不知足咱们的这个需求! 栗子2:查询出全部合同,而且若是其历史合同金额有过300则展现其合同记录信息。 在这个需求下,咱们把查询条件放在on中就是正确的,这时是不能放在where中的。
四、right outer join右外链接
一般简称为右链接,outer可省略,写为:right join; 与左链接相反,右链接以右表为主表,即以右表记录为基础,扩展查询左表信息; 通常可与左链接相互转换,例如上栗1用右链接能够写成以下sql:
SELECT * FROM contract_history a RIGHT JOIN contract b ON a.fk_contract_id = b.id WHERE a.hi_contract_amount = 300
结果:
链接条件一样须要注意位置,可总结为: 一、主表条件放在where中,从表条件按照需求选择放在on中或是where中! 二、当从表条件放在on中时,该条件不影响返回的结果集记录数,可是放在where中则会筛选主表记录!
五、full outer join全链接
全链接,即只要其中某个表存在匹配,full join关键字就会返回行。在mysql中并不支持full join,但能够用left join和right join查询后再union代替,举个栗子:
A表数据:
B表数据:
sql:
SELECT * FROM contract a LEFT JOIN contract_history b ON b.fk_contract_id = a.id UNION SELECT * FROM contract a RIGHT JOIN contract_history b ON b.fk_contract_id = a.id
结果:
分析:
从结果中能够看出,全链接会返回A、B表中全部记录,其中有关联的会根据on条件进行整合,没有链接上的记录也会返回。
总结:
SQL中的链接查询使用很是频繁,但其中的一些细节还须要平时多注意,好比: 一、左、右链接时的条件放置位置及其区别; 二、一对多关系时,在左、右外链接时,若“一”为主表(或内链接)时,查询结果集主表记录会有重复!若要统计主表记录时则需去重。
以上是笔者在平时工做中用到sql的链接查询时总结出来的知识,分享给你们,但愿对读者有帮助!若有错误请给我留言,我会及时更正,谢谢!