一、分類 在多表關聯查詢時,常常要用到鏈接查詢,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的鏈接查詢時總結出來的知識,分享給你們,但願對讀者有幫助!若有錯誤請給我留言,我會及時更正,謝謝!