MySQL中的聯表查詢與子查詢

  • 0.準備數據
  • 1.內鏈接:INNER JOIN
  • 2.左鏈接:LEFT JOIN
  • 3.右鏈接:RIGHT JOIN
  • 4.USING子句
  • 擴展知識點:
    • 0.表別名的使用:
    • 1.group by的用法
    • 2.子查詢
      • 1)不相關子查詢
      • 2)相關子查詢

JOIN的含義就如英文單詞「join」同樣,鏈接兩張表,語法以下所示:html

SELECT * FROM A INNER|LEFT|RIGHT JOIN B ON conditionmysql

JOIN 按照功能大體分爲以下三類:sql

INNER JOIN(內鏈接,或等值鏈接):取得兩個表中存在鏈接匹配關係的記錄。數據庫

LEFT JOIN(左鏈接):取得左表(A)徹底記錄,便是右表(B)並沒有對應匹配記錄。app

RIGHT JOIN(右鏈接):與 LEFT JOIN 相反,取得右表(B)徹底記錄,便是左表(A)並沒有匹配對應記錄。ide

注意:mysql不支持Full join,不過能夠經過UNION 關鍵字來合併 LEFT JOIN 與 RIGHT JOIN來模擬FULL join.性能

 

0.準備數據

表數據
命令
 
blog 記錄文章名與文章類型

create table blog(測試

                id INT primary key auto_increment,大數據

                title_name varchar(40),spa

                title_type int

        );

insert into blog values(0,'aa',1),(0,'bb',2),(0,'cc',3),(0,'dd',4),(0,'ee',3),(0,'ff',2),(0,'gg',default),(0,'hh',6);
 
blog_type 記錄文章類型

  create table blog_type(

                id INT primary key auto_increment,

                name varchar(40)

        );

insert into blog_type values(0,'C'),(0,'PYTHON'),(0,'JAVA'),(0,'HTML'),(0,'C++');

 

 

1.內鏈接:INNER JOIN

內鏈接INNER JOIN/JOIN是最經常使用的鏈接操做。從數學的角度講就是求兩個表的交集:

  • select * from blog inner join blog_type on blog.title_type=blog_type.id;
  • select * from blog join blog_type on blog.title_type=blog_type.id;
  • select * from blog,blog_type where blog.title_type=blog_type.id;

輸出結果:


2.左鏈接:LEFT JOIN

左鏈接LEFT JOIN的含義就是求兩個表的交集外加左表剩下的數據,左鏈接從左表(A)產生一套完整的記錄,與匹配的記錄(右表(B)) .若是沒有匹配,右側將包含null

  • select * from blog left join blog_type on blog.title_type=blog_type.id;


若是想只從左表(A)中產生一套記錄,但不包含右表(B)的記錄,能夠經過設置where語句來執行,以下:

  • select * from blog left join blog_type on blog.title_type=blog_type.id where blog_type.id is null;

3.右鏈接:RIGHT JOIN

同理右鏈接RIGHT JOIN就是求兩個表的交集外加右表剩下的數據。

select * from blog right join blog_type on blog.title_type=blog_type.id;

4.USING子句

MySQL中鏈接SQL語句中,ON子句的語法格式爲:table1.column_name = table2.column_name。當模式設計對聯接表的列採用了相同的命名樣式時,就可使用 USING 語法來簡化 ON 語法,格式爲:USING(column_name)。 因此,USING的功能至關於ON,區別在於USING指定一個屬性名用於鏈接兩個表,而ON指定一個條件。另外,SELECT *時,USING會去除USING指定的列,而ON不會。實例以下。

create table blog_type_1 as select * from blog_type;

 alter table blog_type drop id;alter table blog_type add title_type int not null primary key auto_increment first;

mysql
結果
其餘

select * from blog inner join blog_type  on blog.title_type=blog_type.title_type;

 
select * from blog join blog_type using(title_type);

USING會去除USING指定的列

join中改善性能的一些注意點:來自https://www.cnblogs.com/fudashi/p/7506877.html

  1. 小表驅動大表可以減小內循環的次數從而提升鏈接效率。
  2. 在被驅動表創建索引可以提升鏈接效率
  3. 優先選擇驅動表的屬性進行排序可以提升鏈接效率

擴展知識點:

0.表別名的使用:

對單表作簡單的別名查詢一般是無心義的。通常是對一個表要看成多個表來操做,或者是對多個表進行操做時,才設置表別名。

1.group by的用法

        MySQL之group by的使用

2.子查詢

嵌套在其它查詢中的查詢稱之爲子查詢或內部查詢,包含子查詢的查詢稱之爲主查詢或外部查詢

1)不相關子查詢

        內部查詢的執行獨立於外部查詢,內部查詢僅執行一次,執行完畢後將結果做爲外部查詢的條件使用

        通常在子查詢中,程序先運行在嵌套在最內層的語句,再運行外層。所以在寫子查詢語句時,能夠先測試下內層的子查詢語句是否輸出了想要的內容,再一層層往外測試,增長子查詢正確率。不然多層的嵌套使語句可讀性很低。

舉慄:想要從數據庫中獲取文章類型是Python的文章列表

A
B

分步執行:

        獲取id: select id from blog_type where name='PYTHON';---->id=2

        獲取文章列表:select title_name from blog where title_type=2;-→title name=(bb,ff)

聯合查詢:

        子查詢的方式:select title_name from blog where title_type=(select id from blog_type where name='PYTHON');

        聯表查詢的方式:select title_name from blog A join blog_type B on A.title_type=B.id where B.name='PYTHON';

2)相關子查詢

        內部查詢的執行依賴於外部查詢的數據,外部查詢每執行一次,內部查詢也會執行一次。每一次都是外部查詢先執行,取出外部查詢表中的一個元組,將當前元組中的數據傳遞給內部查詢,而後執行內部查詢。

        根據內部查詢執行的結果,判斷當前元組是否知足外部查詢中的where條件,若知足則當前元組是符合要求的記錄,不然不符合要求。而後,外部查詢繼續取出下一個元組數據,執行上述的操做,直到所有元組均被處理完畢。

舉慄:從歷史最好記錄的表中獲取各個指標最新時間的值

表數據:

藍色框框中的fr指標數據是重複的,預期想要獲取各個指標最新時間的指標值

相關子查詢
聯表查詢
select * from test_best_history_for_storm_largescale t where date =(select max(date) from test_best_history_for_storm_largescale where fr=t.fr and area="largescale_fuji") and area="largescale_fuji"; select * from test_best_history_for_storm_largescale A join (select max(date) date,fr from test_best_history_for_storm_largescale where area='largescale_fuji' group by fr)B on A.date=B.date and A.fr=B.fr and A.area='largescale_fuji';

結果:

結果:

另外一種子查詢方式:
select * from best_history_for_storm_largescale a where not exists (select * from best_history_for_storm_largescale b where a.area=b.area and a.best_history_data+0<b.best_history_data+0 and a.fr=b.fr) and a.area='largescale_fuji';
 
在複習這一塊的知識點使用較大數據量進行測試時,發現使用子查詢使用的時間要比聯表查詢長,後續有時間會再比較性能問題。
相關文章
相關標籤/搜索