MySQL中的聯表查詢與子查詢


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

JOIN的含義就如英文單詞“join”一樣,連接兩張表,語法如下所示:

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

JOIN 按照功能大致分為如下三類:

INNER JOIN(內連接,或等值連接):取得兩個表中存在連接匹配關系的記錄。

LEFT JOIN(左連接):取得左表(A)完全記錄,即是右表(B)並無對應匹配記錄。

RIGHT JOIN(右連接):與 LEFT JOIN 相反,取得右表(B)完全記錄,即是左表(A)並無匹配對應記錄。

注意: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),

                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';
 
在復習這一塊的知識點使用較大數據量進行測試時,發現使用子查詢使用的時間要比聯表查詢長,后續有時間會再比較性能問題。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM