1. 程式人生 > >【T-SQL基礎】02.聯接查詢

【T-SQL基礎】02.聯接查詢

概述:

本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。

【T-SQL基礎】06.透視、逆透視、分組集

【T-SQL基礎】07.資料修改

【T-SQL基礎】09.可程式設計物件

 ----------------------------------------------------------

 ----------------------------------------------------------

【T-SQL效能調優】02.Transaction Log的使用和效能問題

【T-SQL效能調優】03.執行計劃

【T-SQL效能調優】04.死鎖分析

持續更新......歡迎關注我!

本篇主要是對多表查詢基礎的總結。

查詢語句的FROM字句在邏輯上是第一條要處理的字句,在FROM字句內可以用表運算子對輸入的表進行操作。

SQL Server 2008支援四中表運算子:JOIN/APPLY/PIVOT/UNPIVOT

 

一、交叉聯接

1.什麼是交叉聯接

1)對輸入的兩個表進行操作,把它們聯接起來,生成二者的笛卡兒積。

2)將一個輸入表的每行與另一個表的所有行進行匹配。

3)如果一個表有m行,而另一個表有n行,將得到m*n的結果集。

2.語法

先建立兩張表A,C,如下圖所示

1ANSI SQL-92語法

下面的查詢是對A表和C表進行交叉聯接查詢

SELECT A.a,C.c FROM A

CROSS JOIN C

因為A表有4行,C表有5行,所以這個查詢會生成一個包含4*5=20行的資料的結果集。

使用ANSI SQL-92語法,需要在參與聯接的兩個表之間使用“Cross JOIN”關鍵字

2ANSI SQL-89語法

FROM的表名之間加個逗號

SELECT A.a,C.c FROM A,C

這兩種語法在邏輯上和效能上都沒有區別。

3.自交叉聯接

對同一個表進行聯接,就是自聯接。交叉聯接、內聯接、外聯接都支援自聯接。

SELECT A1.a,A2.a FROM A AS A1
CROSS JOIN A AS A2

A表有4行,查詢會生成一個包含4*4=16行的資料的結果集

在自聯接中,必須為表起別名。如果不為表指定別名,聯接結果中的列名就會有歧義。

比如在本例中,別名為A1,A2

二、內聯接

1.什麼是內聯接

對兩個輸入表進行笛卡爾積,然後根據指定的謂詞對結果行進行過濾。

2.語法

1ANSI SQL-92語法

  a.在兩個表名之間指定INNER JOIN關鍵字

  b.INNER關鍵字可選,因為內聯接是預設的聯接方式

  c.對行進行過濾的謂詞是在一個稱為ON字句中指定的,該謂詞也稱為聯接條件

例如查詢A表和C表執行內聯接運算,根據謂詞條件A.id=C.id對錶A和表B進行匹配:

SELECT  A.id ,
        A.a ,
        C.id ,
        C.c
FROM    dbo.A
        INNER JOIN C ON C.id = A.id

怎麼理解內聯接:

  理解內聯接最容易的方法是認為A表中每一行同C表中的所有行進行比較,如果A表中的idC表中的id相等,則匹配成功。

  另外一種更正式的方法是在關係代數的基礎上來考慮內聯接,聯接運算首先對兩個表求笛卡爾積(4A記錄*5C記錄=20行記錄),然後根據條件C.id=A.id對行進行過濾,最終返回16行。

注意:

  ON字句與WHEREHAVING字句類似,ON字句也只返回令謂詞結果為TRUE的行,而不會返回令為此計算結果為FALSEUNKNOW的行。

2ANSI SQL-89語法

和交叉聯接類似,內聯接可以在表名之間用“,”來表示聯接,然後用WHERE字句中定義聯接條件。

SELECT  A.id ,
        A.a ,
        C.id ,
        C.c

FROM    dbo.A ,
        dbo.C
WHERE   A.id = C.id

內聯接的這兩種語法執行結果和效能是一樣的,但是推薦是用ANSI SQL-92語法。因為ANSI SQL-92語法更安全。

原因有兩點:

  a.因為如果用內聯接查詢,但是忘了寫ON條件,則語法分析器會報錯,執行無效;

  b.使用ANSI SQL-89標準,有可能忘了WHERE字句中的聯接,但是語法分析器不會報錯,且執行成功。

對於交叉聯接來說,也是推薦使用ANSI SQL-92語法。

原因有兩點:

  a.保持一致,統一使用ANSI SQL-92語法

  b.如果開發人員本來是想用ANSI SQL-89語法來寫一個內聯接查詢,卻又忘了寫WHERE字句中的聯接條件,則這段SQL的聯接型別和交叉聯接是一樣的。另外的開發人員再來看的時候並不能判斷前面的開發人員到底是想內聯接查詢還是交叉聯接。

3.特殊的聯接例項

1)組合聯接

組合聯接就是聯接條件涉及聯接兩邊的多個列的查詢。當需要根據主鍵-外來鍵關係來聯接兩個表而且主外來鍵關係是組合的(即關係基於多個列)時,通常使用組合聯接。

B表定義了一個外來鍵(id1,id2),引用了D表的id1,id2列,現在要寫一個主外來鍵關係來聯接兩個表的查詢。

SELECT  *
FROM    B
INNER JOIN D
ON D.id1 = B.id1
AND D.id2 = B.id2

2)不等聯接

聯接條件只包含等號運算子,叫做等值聯接,聯接條件包含除等號以外的其他運算子,叫做不等聯接。

SELECT    *
FROM      A
INNER JOIN C
ON dbo.A.id < dbo.C.id

如果使用交叉聯接,得到的結果中將包含自偶對(例如,11),以及映象對(例如,1221.使用內聯接,並在聯接條件中指定左邊的鍵值要小於右邊的鍵值,就可以消除這兩種沒有用的情況。

3)多表聯接

FROM子句中包含多個表運算子時,表運算子在邏輯上是按從左到右的順序處理的。

A和表B進行JOIN關聯,得到結果集ABAB將作為第二個表運算子JOIN的輸入,與表C進行JOIN關聯,得到結果ABC,以此類推。

所以如果FROM字句包含多個連線,邏輯上只有第一個聯接對兩個基礎表進行操作,而其他聯接則將前一個聯接的結果作為其左邊的輸入。

三、外聯接

1.什麼是外聯接

對兩張表進行笛卡爾積,ON過濾,新增外部行

2.語法

只有ANSI SQL-92語法

表名之間用

LEFT OUTER JOIN

RIGHT OUTER JOIN

FULL OUTER JOIN

ON字句中進行過濾

3.外聯接基礎

1LEFT關鍵字標識左邊表的行駛保留的,RIGHT關鍵字表示右邊的行是保留的,FULL關鍵字則表示左右兩邊表的行都是保留的。

2)外聯接的第三個邏輯查詢處理步驟就是要識別保留表中按照ON條件在另一個表找不到與之匹配的那些行,再把這些行新增到聯接的前兩個步驟生成的結果表中。

3)對於來自聯接的非保留表的那些列,追加的外部行中的這些列則用NULL作為佔位符。

集合A包含兩個集合,集合A1和集合A2,集合B包含兩個集合,集合B1和集合B2AB的交集是A2B2

AB進行LEFT OUTER JOIN後,A1A2都保留,因A1B中找不到對應的資料,則A1對應的行需要保留,新增到聯接的前兩個步驟生成的結果表中,而對於非保留表的列,在外部行中則用NULL作為佔位符。

例子:

客戶的ID和訂單的客戶IDCustomer表和Orders表進行關聯,並返回客戶和他們的訂單資訊。

Customer包含兩部分:有訂單的客戶,沒有訂單的客戶,用左外聯接,查詢結果返回有訂單的客戶和沒有訂單的客戶:

SELECT  Cus.custid ,
        o.orderid
FROM    Sales.Customers AS Cus
        LEFT OUTER JOIN Sales.Orders AS O 
        ON Cus.custid = O.custid

我們可以通過下面的查詢,查詢出沒有訂單的客戶

SELECT  Cus.custid ,
        O.orderid ,
        O.custid ,
        O.orderdate ,
        O.requireddate ,
        O.shippeddate
FROM    Sales.Customers AS Cus
        LEFT OUTER JOIN Sales.Orders AS O ON Cus.custid = O.custid
WHERE   o.custid IS NULL

1.他們的ID分別為2257。查詢結果中這兩個客戶在Order表中的列都為NULL

2.從邏輯上說,這兩個客戶相關的資料行在聯接的第二步(基於ON謂詞條件的過濾)就被過濾了,而在第三部又把這些行作為外部行添加了進來。

3.如果使用內聯接,結果將不會返回這兩行。新增這兩行後,就可以在結果中保留左邊表的所有行。

4.外聯接結果可以看作兩種,內不行和外部行,內部行是ON字句的條件能在另一邊找到匹配的那些行;外部行則是找不到那些行。內聯接只返回內不行,而外聯接返回內部行和外部行。

5.ON字句中的條件不能最終決定保留表中部分行是否會在結果中出現,當決定哪些行可以匹配非保留表,就在ON字句中指定聯接條件。當在生成外部行以後,要應用外部行以後,要應用過濾器,而且希望過濾條件是最終的。就應該在WHERE字句中指定條件。

4.在多表聯接中使用外聯接

1.對外聯接的處理順序進行調整,可能會得到不同的輸出結果,所以不能隨意調整它們的順序。

2.對於任何外聯接(左外聯接欸、右外聯接、和全外聯接),如果後面緊跟著一個內聯接或右外聯接,都會抵消外聯接的外部行。前提是,聯接條件對來自聯接左邊的NULL值和聯接右邊的某些值進行了比較。

四、多表查詢-幾道SQL查詢題

表間關係圖

在做下面的題目之前,我們可以先把環境準備好,以下的SQL指令碼可以幫助大家建立資料庫,建立表,插入資料。

1.返回來自美國的客戶,併為每個客戶返回訂單總數和商品交易總數量。

本題是一道外聯接查詢,需要查詢出所有客戶(有訂單的客戶和沒有訂單的客戶)對應的訂單總數,然後再與訂單詳情關聯,查詢出每個客戶對應的所有訂單上的所有的商品的交易總數量。

然後篩選出country = 'USA'。為了得到每個客戶的訂單總數,需要用COUNT(DISTINCT O.orderid)進行統計。

SELECT  C.custid ,
        COUNT(DISTINCT O.orderid) AS numorders ,
        SUM(CASE WHEN qty IS NULL THEN 0 ELSE qty END) AS totalqty

FROM    Sales.Customers AS C
        LEFT OUTER JOIN Sales.Orders AS O ON O.custid = C.custid
        LEFT OUTER JOIN Sales.OrderDetails D ON D.orderid = O.orderid
WHERE   country = 'USA'
GROUP BY C.custid

2.返回客戶及其訂單資訊,包括沒有下過任何訂單的客戶。

SELECT  C.custid ,
        C.companyname ,
        O.orderid ,
        O.orderdate
FROM    Sales.Customers AS C
        LEFT OUTER JOIN Sales.Orders AS O 
        ON O.custid = C.custid

3.返回在2007212日下過訂單的客戶,以及他們的訂單。同時也返回在2007212日沒有下過訂單的客戶。

這題主要考察在聯接查詢中,ONWHERE的用法。

1)訂單日期的過濾過濾條件必須出現在ON字句,而不是WHERE字句中。WHERE過濾條件是在外部行被新增以後才被應用的,而且是最終的。

2)訂單的日期的過濾條件只是用於決定是否匹配,但不是決定客戶行的最終條件。

SELECT  C.custid ,
        C.companyname ,
        O.orderid ,
        O.orderdate
FROM    Sales.Customers AS C
        LEFT OUTER JOIN Sales.Orders AS O
        ON O.custid = C.custid
        AND O.orderdate = '20070212'

參考資料:

《SQL2008技術內幕:T-SQL語言基礎》


作  者:
出  處:http://www.cnblogs.com/jackson0714/
關於作者:專注於微軟平臺的專案開發。如有問題或建議,請多多賜教!
版權宣告:本文版權歸作者和部落格園共有,歡迎轉載,但未經作者同意必須保留此段宣告,且在文章頁面明顯位置給出原文連結。
特此宣告:所有評論和私信都會在第一時間回覆。也歡迎園子的大大們指正錯誤,共同進步。或者直接私信
聲援博主:如果您覺得文章對您有幫助,可以點選文章右下角推薦一下。您的鼓勵是作者堅持原創和持續寫作的最大動力!

相關推薦

T-SQL基礎02.聯接查詢

概述: 本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。 【T-SQL基礎】06.透視、逆透視、分組集 【T-SQL基礎】07.資料修改 【T-SQL基礎】09.可程式設計物件  ------------------------------------------

T-SQL基礎03.子查詢

引用 鏈接 編程 pac tom 單表 獨立 但是 company 閱讀目錄 概述: 一、獨立子查詢 二、相關子查詢 三、練習題 以前總是追求新東西,發現基礎才是最重要的,今年主要的目標是精通SQL查詢和SQL性能優化。 本系列【T-SQL基礎】主要是針對T-S

T-SQL基礎01.單表查詢-幾道sql查詢

概述: 本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。 【T-SQL基礎】06.透視、逆透視、分組集 【T-SQL基礎】07.資料修改 【T-SQL基礎】09.可程式設計物件  ------------------------------------------

traits-traitsui-基礎-02-控制元件Str/Button

微信公眾號原文 系統:Windows 7 語言版本:Anaconda3-4.3.0.1-Windows-x86_64 編輯器:JetBrains PyCharm Community Edition 2016.3.2 本系列介紹traits,traitsui的一些

T-SQL進階02.理解SQL查詢的底層原理

本系列【T-SQL】主要是針對T-SQL的總結。 一、SQL Server組成部分 1.關係引擎:主要作用是優化和執行查詢。 包含三大元件: (1)命令解析器:檢查語法和轉換查詢樹。 (2)查詢優化器:優化查詢。 (3)查詢執行器:負責執行查詢。 2.儲存引擎:管理所有資料及涉及的IO

刷題-----資料庫SQL實戰查詢的員工號emp_n薪水漲幅超過15次o以及其對應的漲幅次數t(親測正確的)

題目描述 查詢薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL, `salary` int(11) NOT NULL, `from_date` date NO

資料庫SQL實戰查詢薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t

題目描述 查詢薪水漲幅超過15次的員工號emp_no以及其對應的漲幅次數t CREATE TABLE `salaries` ( `emp_no` int(11) NOT NULL, `salary

T-SQL基礎(一)之簡單查詢

名詞解釋 SQL: Structured Query Language,結構化查詢語言,是一種在關係型資料庫中用於管理資料的標準語言。SQL是一種宣告式程式語言,即只需表明需要什麼而無需關注實現細節(C#中的LINQ也是如此)。 SQL方言:在SQL基礎上延伸的其它語言,如SQL Server中

T-SQL基礎(二)之關聯查詢

在上篇博文中介紹了T-SQL查詢的基礎知識,本篇主要介紹稍微複雜的查詢形式。 表運算子 表運算子的作用是把為其提供的表作為輸入,經過邏輯查詢處理,返回一個表結果。SQL Server支援四個表運算子:JOIN、APPLY、PIVOT、UNPIVOT,其中JOIN是標準SQL中的運算子,APPLY、PIVO

T-SQL效能優化01.TempDB的使用和效能問題

以前總是追求新東西,發現基礎才是最重要的,今年主要的目標是精通SQL查詢和SQL效能優化。 本系列【T-SQL基礎】主要是針對T-SQL基礎的總結。 一、TempDB是什麼? 1.TempDB是一個系統資料庫。從SQL Server2000開始就一直存在。 2.只有Simple恢復模式

T-SQL系列文章全文目錄(2017-06-26更新)

作  者: 出  處:http://www.cnblogs.com/jackson0714/ 關於作者:專注於微軟平臺的專案開發。如有問題或建議,請多多賜教! 版權宣告:本文版權歸作者和部落格園共有,歡迎轉載

資料庫SQL實戰查詢所有員工自入職以來的薪水漲幅情況

https://www.nowcoder.com/practice/fc7344ece7294b9e98401826b94c6ea5?tpId=82&tqId=29773&rp=0&ru=/ta/sql&qru=/ta/sql/q

第16講++T-SQL基礎知識

from logs http splay msg 分享 ++ sel 學生表 分別定義一個整型變量和兩個字符型變量。 declare @name varchar(10) declare @age smallint , @msg

數理統計基礎 05 - 回歸分析

關於 以及 區間估計 否則 del 相互 不同之處 最小二乘 研究   參數估計和假設檢驗是數理統計的兩個基礎問題,它們不光運用於常見的分布,還會出現在各種問題的討論中。本篇開始研究另一大類問題,就是討論多個隨機變量之間的關系。現實生活中的數據雜亂無章,夠挖掘出各種變量之間

微信開發02.搭建一個屬於自己的微信公眾平臺

tro 投票 新浪 關系 blank 訂閱 logs name 開發者 閱讀目錄 【網站開發】在新浪SAE上搭建一個博客 概述   公司年會上同事開發了一個微信企業號,包含了投票,抽獎,祝福墻功能,還開了一個Session,跟我們講了下公司的企業號開發過程和抽獎中獎

JAVAEE學習筆記hibernate04:查詢種類、HQL、Criteria、查詢優化和練習為客戶列表增加查詢條件

沒有 arrays getpara tex response 寫法 sum exceptio 提高 一、查詢種類 1.oid查詢-get 2.對象屬性導航查詢 3.HQL 4.Criteria 5.原生SQL 二、查詢-HQL語法 //學習HQL語法 public

項目基礎容器、AOP理論篇

b2c 需求 mark 配置 mod 維護 term -s 強制 一、容器(砂鍋) 1、概念: 容器是應用server中位於組件和平臺之間的接口集合 2、應用: 容器一般位於應用server之內,由應用server負責載入

ADO.NET基礎加密方法經典集合

char 自定義 rst reac stream algorithm array temp esc 各種加密方法集錦: using System; using System.Security.Cryptography; using System.Text; using S

編程基礎C語言常見宏定義

ifd 轉換成 erro get 程序 運算 efi 宏定義 當前 我們在使用C語言編寫程序的時候,常常會使用到宏定義以及宏編譯指令,有的可能比較常用,有的可能並不是很常用,是不是所有的C語言宏定義以及宏指令你都清楚呢? 指令 用途詳細介紹 # 空指令,無任何效果 #i

計算機網絡基礎數據鏈路層(目錄)

計算機網絡 劃分 靜態 控制 網橋 透明 回退 csma/cd 廣播 數據鏈路層知識結構 數據鏈路層組幀和透明傳輸 數據鏈路層差錯檢驗 奇偶校驗 循環冗余校驗(CRC) 海明碼 數據鏈路層可靠傳輸(ARQ協議) 停止-等待協議 回退N幀協議(GBN協議) 選擇重傳協