SQL鏈接查詢研究

一、分類 在多表關聯查詢時,常常要用到鏈接查詢,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

image.png B:ci

image.png

內鏈接查詢:io

select * from contract a INNER JOIN contract_history b on a.id=b.fk_contract_id

結果:效率

image.png

分析:基礎

一、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

結果:

image.png

分析:

從結果能夠看出,雖然合同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

結果:

image.png

結果知足咱們的需求,可是若是把篩選條件放在on中:

SELECT
	*
FROM
	contract a
LEFT JOIN contract_history b ON a.id = b.fk_contract_id
AND b.hi_contract_amount = 300

結果:

image.png

顯然,查詢結果不知足咱們的這個需求! 栗子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

結果:

image.png

鏈接條件一樣須要注意位置,可總結爲: 一、主表條件放在where中,從表條件按照需求選擇放在on中或是where中! 二、當從表條件放在on中時,該條件不影響返回的結果集記錄數,可是放在where中則會篩選主表記錄!

五、full outer join全鏈接

全鏈接,即只要其中某個表存在匹配,full join關鍵字就會返回行。在mysql中並不支持full join,但能夠用left join和right join查詢後再union代替,舉個栗子:

A表數據:

image.png

B表數據:

image.png

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

結果:

image.png

分析:

從結果中能夠看出,全鏈接會返回A、B表中全部記錄,其中有關聯的會根據on條件進行整合,沒有鏈接上的記錄也會返回。

總結:

SQL中的鏈接查詢使用很是頻繁,但其中的一些細節還須要平時多注意,好比: 一、左、右鏈接時的條件放置位置及其區別; 二、一對多關係時,在左、右外鏈接時,若「一」爲主表(或內鏈接)時,查詢結果集主表記錄會有重複!若要統計主表記錄時則需去重。

以上是筆者在平時工做中用到sql的鏈接查詢時總結出來的知識,分享給你們,但願對讀者有幫助!若有錯誤請給我留言,我會及時更正,謝謝!

相關文章
相關標籤/搜索