連接查詢、子查詢、聯合查詢
連接查詢
交叉連接 t1 cross join t2
內連接:t1 inner join t2 on 。。滿足條件的交集
左外連接: t1 left join t2 on 。。 以左表為主表,取出每一條與另一張對比,條件不匹配非主表字段都置位null
自然內連接和外連接: t1 natural t2, t1 natural left t2以同名字段連接
全連接Full outer join:會產生兩個表的並集,不匹配的地方會被置位null,結果集中會出現兩個name相同的,以及某一個name為null的結果(所有的連接都是這樣,除了內連接,內連接的on和where一樣)
SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name
選擇兩個表的去除交集的數據集:(控制主鍵為null,這樣相當於除掉交集)
SELECT * FROM TableA FULL OUTER JOIN TableB ON TableA.name = TableB.name WHERE TableA.id IS null OR TableB.id IS null
Mysql沒有全連接,只能用這種語法實現full join:(兩次外連接union)
select * from t1 left join t2 on t1.id = t2.id
union
select * from t1 right join t2 on t1.id = t2.id;
mysql只能用這種方式實現兩個表去除交集的數據集:(兩次外連接同時用where限制null然后union)
select * from t1 left join t2 on t1.id = t2.id where t2.id is null
-> union
-> select * from t1 right join t2 on t1.id = t2.id where t1.id is null;
左表獨有數據(利用置空另一張表的主鍵):select * from t1 left join t2 on t1.id = t2.id where t2.id is null;
連接分為首先要查的表(驅動表)和被驅動表,對外連接來說這個是固定的,內連接根據優化器優化結果來確定誰作為什么表。驅動表查詢的結果放入一個叫join buffer的區域,然后查詢被驅動表依次與join buffer中的數據對比。
內連接中where和on是等效的,from后跟多個數據源就相當於內連接,外連接中不符合on條件的記錄最后也會在結果中,不符合where的不會加入結果
子查詢
分為標量子查詢(只有一個數作為結果的查詢)、行子查詢(返回一個行記錄)、列子查詢(返回一列值)、表子查詢。
也可分為相關子查詢(子查詢內限制條件與外層表有關)、和不相關子查詢
子查詢在執行時首先會嘗試是否能轉換為兩次獨立的單表查詢,然后再嘗試轉換為半連接,將子查詢轉換成一種類似連接查詢的查詢來執行,不同之處在於關心滿足條件不再關心滿足條件的記錄多少,如果數據太多會將子查詢結果保存在一個臨時表內,這個表稱為物化表(一般放在內存中除非實在太大),並為該表建立哈希索引或b+索引,還可能將in子查詢轉換成exists子查詢以命中索引。
(半連接:假如有一條語句select * from s1 where key1 in(select key2 from s2)這條語句可以理解成如果對s1表某條記錄,如果能在s2中找到一條或多條記錄s2的key2=key1的,那么這條記錄最后就會被加入結果集中,其實和連接查詢很像:select s1.* from s1 inner join s2 on s1.key1 = s2.key2,只不過現在不關心s2中具體什么記錄匹配,而是是否有記錄匹配,這樣的邏輯依然可以簡化查詢,被稱為半連接)
聯合查詢
Select句1 union(all/distinct)select句2,查詢結果拼接
拼接的兩個select語句查詢的列數和列數據類型必須相同,union會去處相同的記錄,而union all會將相同的記錄保留(所謂相同就是每個列都必須相同)