<output id="qn6qe"></output>

    1. <output id="qn6qe"><tt id="qn6qe"></tt></output>
    2. <strike id="qn6qe"></strike>

      亚洲 日本 欧洲 欧美 视频,日韩中文字幕有码av,一本一道av中文字幕无码,国产线播放免费人成视频播放,人妻少妇偷人无码视频,日夜啪啪一区二区三区,国产尤物精品自在拍视频首页,久热这里只有精品12
      Fork me on GitHub

      SQL Join的一些總結

      1.1.1 摘要

      Join是關系型數據庫系統的重要操作之一,SQL Server中包含的常用Join:內聯接、外聯接和交叉聯接等。如果我們想在兩個或以上的表獲取其中從一個表中的行與另一個表中的行匹配的數據,這時我們應該考慮使用Join,因為Join具體聯接表或函數進行查詢的特性

      本文將通過具體例子介紹SQL中的各種常用Join的特性和使用場合:

      目錄

      1.1.2 正文

      首先我們在tempdb中分別定義三個表College、Student和Apply,具體SQL代碼如下:

      USE tempdb
      
      ---- If database exists the same name datatable deletes it.
      IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'College') DROP TABLE College;
      IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Student') DROP TABLE Student;
      IF EXISTS(SELECT TABLE_NAME FROM INFORMATION_SCHEMA.TABLES WHERE TABLE_NAME = 'Apply') DROP TABLE Apply;
      
      ---- Create Database.
      create table College(cName nvarchar(50), state text, enrollment int);
      create table Student(sID int, sName nvarchar(50), GPA real, sizeHS int);
      create table Apply(sID int, cName nvarchar(50), major nvarchar(50), decision text);

      Inner join

      內聯接(Inner join)是最常用的聯接類型之一,它查詢滿足聯接謂詞的數據。

      假設我們要查詢申請表Apply中申請學校的相關信息,由于Apply表中包含學校名字我們并不能預知,所以我們可以根據cName來內聯接(Inner join)表College和Apply,從而找到Apply表中包含學校的信息。

      具體SQL代碼如下:

      ---- Gets college information from college table
      ---- bases on college name.
      SELECT DISTINCT College.cName, College.enrollment
      FROM  College INNER JOIN
              Apply ON College.cName = Apply.cName

      join0

      圖1查詢結果

      cName state enrollment
      Stanford CA 15000
      Berkeley CA 36000
      MIT MA 10000
      Cornell NY 21000
      Harvard MA 29000

      表1 College表中的數據

      如上圖1所示,我們把Apply表包含的學校信息查詢出來了,由于Harvard并沒有被查詢出來,所以我們知道暫時還沒有學生申請Harvard。

      內聯接(Inner join)滿足交換律:“A inner join B” 和 “B inner join A” 是相等的。

      Outer join

      假設我們想看到所有學校信息;即使是那些沒有申請的學校(如:Harvard),這時我們可以使用外部聯接(Outer join)進行查詢。由于外部聯接保存一個或兩個輸入表的所有行,即使無法找到匹配聯接謂詞的行。

      具體SQL代碼如下:

      ---- Gets all college information
      SELECT College.cName, College.state, College.enrollment,
      Apply.cName, Apply.major, Apply.decision
      FROM  College LEFT OUTER JOIN
              Apply ON College.cName = Apply.cName

      join3

      圖2左聯接查詢結果

      如上圖3所示:由于在Apply表中并沒有學生申請Harvard,但是我們通過左聯接(left outer join)把所有學校信息查詢出來了。

      由于左聯接(left outer join)產生表College的完全集,而Apply表中匹配的則有值,而不匹配的則以NULL值取代,所以我們知道Apply表中沒有學生申請Harvard。

      通過左聯接查詢我們可以獲取College的完全集,假設現在我們既要獲取College的完全集又要獲取Apply的完全集,那么我們可以考慮使用完整外部聯接(full outer join)。使用完整外部聯接,我們可以查詢所有的學校,不管它們是否匹配聯接謂詞:

      ---- Gets all information from college and apply table.
      SELECT College.cName, College.state, College.enrollment,
      Apply.cName, Apply.major, Apply.decision
      FROM  College FULL OUTER JOIN
              Apply ON College.cName = Apply.cName 

      join4

      圖3 完整外部聯接查詢結果

      現在我們獲取了College和Apply的完全數據集,對于表中匹配的則有值,即使沒有找到匹配cName的則以NULL值取代。

      下表顯示每種外部聯接(outer join)匹配時保留數據行的情況:

      聯接類型

      保留數據行

      A left outer join B

      all A rows

      A right outer join B

      all B rows

      A full outer join B

      all A and B rows

      表2 外部聯接保留數據行

      完整外部聯接(full outer join)滿足交換律:“A full outer join B” 和 “B full outer join A” 是相等的。

      Cross join

      交叉聯接(cross join)執行兩個表的笛卡爾積(就是把表A和表B的數據進行一個N*M的組合)。也就是說,它匹配一個表與另一個表中的每一行;我們不能通過使用ON子句在交叉聯接指定謂詞,雖然我們可以使用WHERE子句來實現相同的結果,這是交叉聯接基本上是作為一個內部聯接了。

      交叉聯接相對于內部聯接使用率較低,而且兩個大表不應該進行交叉聯接,因為這將導致一個非常昂貴的操作和一個非常大的結果集。

      具體SQL代碼如下:

      ---- College Cross join Apply.
      SELECT College.cName, College.state, College.enrollment,
      Apply.cName, Apply.major, Apply.decision
      FROM College
      CROSS JOIN Apply
      join5

      圖4 College表和Apply表的行數

      join6

      圖5 交叉聯接

      現在我們對College和Apply表進行交叉聯接,而且生成數據行為College和Apply表行數的笛卡爾積即5 * 20 = 100。

      Cross apply

      在SQL Server 2005中提供了Cross apply使表可以和表值函數(table-valued functions TVF‘s)結果進行join查詢。例如,現在我們想通過函數的結果值和表Student進行查詢,這時我們可以使用Cross apply進行查詢:

      ---- Creates a function to get data from Apply base on sID.
      CREATE FUNCTION dbo.fn_Apply(@sID int)
      RETURNS @Apply TABLE (cName nvarchar(50), major nvarchar(50))
      AS
      BEGIN
        INSERT @Apply SELECT cName, major FROM Apply where [sID] = @sID
        RETURN    
      END
       
      ---- Student cross apply function fn_Apply.
      SELECT Student.sName, Student.GPA, Student.sizeHS,
      cName, major 
      FROM Student CROSS APPLY dbo.fn_Apply([sID])

      我們也可以使用內部聯接實現和Cross apply相同的查詢功能,具體SQL代碼如下:

      ---- Student INNER JOIN Apply bases on sID.
      SELECT Student.sName, Student.GPA, Student.sizeHS,
      cName, major 
      FROM Student INNER JOIN [Apply]
      ON Student.sID = [Apply].sID

      join7

      圖6 Cross apply查詢

      Outer apply

      在介紹Cross apply和Outer join之后,現在讓我們理解Out apply也就不難了,Outer apply使表可以和表值函數(table-valued functions TVF‘s)結果進行join查詢,找到匹配值則有值,沒有找到匹配值則以NULL表示。

      ---- Student outer apply function fn_Apply.
      SELECT Student.sName, Student.GPA, Student.sizeHS,
      cName, major 
      FROM Student OUTER APPLY dbo.fn_Apply([sID])
      join10

      圖7 Outer apply查詢

      Inner Join和Cross apply的區別

      首先我們知道Inner join是表和表的聯接查詢,而Cross apply是表和表值函數的聯接查詢,在前面Cross apply例子中,我們也可以通過Inner join實現相同的查詢。

      ---- Student cross apply function fn_Apply.
      SET STATISTICS PROFILE ON
      SET STATISTICS TIME ON
      
      SELECT Student.sName, Student.GPA, Student.sizeHS,
      cName, major 
      FROM Student CROSS APPLY dbo.fn_Apply([sID])
      
      SET STATISTICS PROFILE OFF
      SET STATISTICS TIME OFF
      
      
      ---- Student INNER JOIN Apply base on sID.
      SET STATISTICS PROFILE ON
      SET STATISTICS TIME ON
      
      SELECT Student.sName, Student.GPA, Student.sizeHS,
      cName, major 
      FROM Student INNER JOIN [Apply]
      ON Student.sID = [Apply].sID
      
      SET STATISTICS PROFILE OFF
      SET STATISTICS TIME OFF

      Cross apply查詢執行時間:

      CPU 時間= 0 毫秒,占用時間= 11 毫秒。

      Inner join查詢執行時間:

      CPU 時間= 0 毫秒,占用時間= 4 毫秒。

      join8

      圖8 執行計劃

      如圖8所示:Cross apply首先執行TVF(table-valued functions),然后對表Studnet進行全表掃描,接著通過遍歷sID查找匹配值。

      Inner join對表Student和Apply進行全表掃描,然后通過哈希匹配查找匹配的sID值。

      通過以上的SQL執行時間和執行計劃,我們能不能說Inner join比Cross apply好呢?答案是否定的,如果表的數據量很大,那么Inner join的全表掃描耗費時間和CPU資源就增加了(可通過數據量大的表進行測試)。

      雖然大多數采用Cross apply實現的查詢,可以通過Inner join實現,但Cross apply可能產生更好的執行計劃和更佳的性能,因為它可以在聯接執行之前限制集合加入。

      Semi-join和Anti-semi-join

      Semi-join從一個表中返回的行與另一個表中數據行進行不完全聯接查詢(查找到匹配的數據行就返回,不再繼續查找)。

      Anti-semi-join從一個表中返回的行與另一個表中數據行進行不完全聯接查詢,然后返回不匹配的數據。

      不同于其他的聯接運算,Semi-join和Anti-semi-join沒有明確的語法來實現,但Semi-join和Anti-semi-join在SQL Server中有多種應用場合。我們可以使用EXISTS子來實現Semi-join查詢,Not EXISTS來實現Anti-semi-join。現在讓我們通過具體的例子說明吧!

      假設要求我們找出Apply和Student表中sID匹配的學生信息,這和前面的Inner join查詢結果將一樣,具體SQL代碼如下:

      ---- Student Semi-join Apply base on sID.
      SELECT Student.sName, Student.GPA, Student.sizeHS
      ----[Apply].cName, [Apply].major 
      FROM Student
      WHERE exists (
          SELECT *
          from [Apply]
          where [Apply].sID = Student.sID
      )

      我們發現常用的EXISTS子句,原來是通過Left Semi Join實現的,所以說Semi-join在SQL Server中又許多使用場合。

      join13

      圖9 查詢結果

      join12

      圖10 執行計劃

      現在要求我們找出還沒有申請學校的學生信息,這時我們立刻反應可以使用NOT EXISTS子句來實現該查詢,具體SQL代碼如下:

      ---- Gets student still not apply for school.
      SELECT Student.sID, Student.sName, Student.GPA, Student.sizeHS
      ----[Apply].cName, [Apply].major 
      FROM Student
      WHERE NOT EXISTS (
          SELECT *
          FROM [Apply]
          WHERE [Apply].sID = Student.sID
      )
      
      

      其實,我們常用的NOT EXISTS子句的實現是通過Anti-semi-join,通過執行計劃我們發現在查找匹配sID時,SQL使用 Left Anti Semi Join進行查詢。

      join14

      圖11 查詢結果

      join15

      圖12 執行計劃

      1.1.3 總結

      本文介紹了SQL中常用了聯接查詢方式:Inner join、Outer join、Cross join和Cross apply的使用場合和特性。

      系列博文導航

      參考

      SQL代碼

      posted @ 2012-03-27 21:54  JK_Rush  閱讀(157652)  評論(35)    收藏  舉報
      主站蜘蛛池模板: 亚洲AⅤ天堂AV天堂无码| 中文字幕人妻精品在线| 国产目拍亚洲精品二区| 亚洲国产在一区二区三区| 亚洲国产精品成人av网| 国内在线视频一区二区三区| 欧美成人午夜性视频| 国产三级视频网站| 午夜成人理论无码电影在线播放| 亚洲最大成人网色| 国产日韩久久免费影院| 精品激情视频一区二区三区| 她也色tayese在线视频| 欧美日韩国产亚洲沙发| 久久月本道色综合久久| 狠狠爱五月丁香亚洲综| 一本大道久久a久久综合| 国产成人午夜福利院| 在线观看无码av五月花| 中文无码vr最新无码av专区| 午夜成人无码免费看网站| 国产成人永久免费av在线| 国产精品亚洲片夜色在线| 国产亚洲精品中文字幕| 国产粉嫩系列一区二区三| 日本欧美大码a在线观看| 国产精品午夜福利免费看| 国产在线中文字幕精品| 日韩一区国产二区欧美三区 | 51午夜精品免费视频| 日韩一区在线中文字幕| 国产极品粉嫩尤物一线天| 亚洲天堂在线免费| 国产成人精品亚洲资源| 国产亚洲精品综合一区二区| 国产三级精品福利久久| 中文字幕av国产精品| 日本高清视频网站www| 日韩人妻久久精品一区二区| 精品欧美h无遮挡在线看中文 | 亚洲爆乳WWW无码专区|