日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 运维知识 > 数据库 >内容正文

数据库

2008技术内幕:T-SQL语言基础 联接查询摘记

發布時間:2023/12/18 数据库 34 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2008技术内幕:T-SQL语言基础 联接查询摘记 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

?

續 2008技術內幕:T-SQL語言基礎 單表查詢摘記

第三章?聯接查詢

  Microsoft SQL Server 2008 支持四種表運算符 join(ANSI標準)、apply(T-SQL擴展)、pivot(T-SQL擴展)、unpivot(T-SQL擴展)。

  (ANSI SQL是美國國家標準學會(ANSI) 對SQL進行規范化后的國際標準SQL語言,T-SQL是Microsoft SQL Server基于ANSI SQL做了一些擴展形成的專用SQL語言。)

  join表運算符對兩個輸入表進行操作,有三種基本類型:交叉聯接內聯接、外聯接。

  處理步驟

      交叉聯接只有一個步驟--笛卡爾積

      內聯接有兩個步驟--笛卡爾積過濾

      外聯接有三個步驟--笛卡爾積、過濾、添加外部行。

  出于優化的目的,SQL Server關系引擎經常會采用很多處理捷徑(數據庫引擎并沒有嚴格按照邏輯查詢處理步驟),因為他知道這樣的處理仍然能夠生成正確的結果。

?

  交叉聯接

  SQL Server支持交叉聯接的兩種標準語法--ANSI SQL-92 和 ANSI SQL-89 推薦用ANSI SQL-92(下面有推薦說明)。?

--ANSI SQL-92標準 CROSS JOIN 關鍵字 SELECT c.custid ,e.empid FROM Sales.Customers AS cCROSS JOIN hr.Employees AS e --ANSI SQL-89標準 SELECT c.custid ,e.empid FROM Sales.Customers AS c ,hr.Employees AS e

  這兩種語法在邏輯上和性能上都沒有區別,Customers表有91行而Employees有9行數據,所以上面的查詢會生成一個819行數據的結果集。

  笛卡爾積:如果一個表有m行,而另個表有n行,將得到m*n行的結果集。

  圖11

  自交叉聯接:顧名思義一個表實現自己連接自己。交叉聯接、內鏈接、外連接都支持自聯接。上面笛卡爾積圖就是一個自交叉聯接實例。?

SELECT E1.empid ,E1.firstname ,E1.lastname ,E2.empid ,E2.firstname ,E2.lastname FROM hr.Employees AS E1CROSS JOIN hr.Employees AS E2

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

--利用自聯接生成數字表 DECLARE @table TABLE(digit INT NOT NULL PRIMARY KEY) INSERT INTO @table( digit )VALUES ( 0 ),( 1 ),( 2 ),( 3 ),( 4 ),( 5 ),( 6 ),( 7 ),( 8 ),( 9 )SELECT T1.digit + T2.digit * 10 + T3.digit * 100 + 1 AS d FROM @table AS T1CROSS JOIN @table AS T2CROSS JOIN @table AS T3 ORDER BY d

?

  內聯接
    兩個邏輯步驟:一,對兩個輸入的表進行笛卡爾積運算,二,過濾。

  ?--ANSI SQL-92標準
    兩表之間必須指定inner join關鍵字,inner關鍵字是可選的,因為內聯接是默認的聯接方式,可以單獨指定join關鍵字。?

SELECT e.empid ,e.firstname ,e.lastname ,o.orderid FROM hr.Employees AS eJOIN Sales.Orders AS o ON e.empid = o.empid

    on條件子句和where、having子句一樣,只返回結果為true的行,而不會返回謂詞計算結果為false、unknow的行

--ANSI SQL-89標準SELECT e.empid ,e.firstname ,e.lastname ,o.orderid FROM hr.Employees AS e ,Sales.Orders AS o WHERE e.empid = o.empid

?

  語法推薦說明

    在這里,還是強烈推薦使用ANSI SQL-92標準的聯接語法,因為在某些方面它用起來更安全。如果你寫一條內聯接查詢但忘記了指定聯接條件,如果這時候用的是ANSI SQL-92標準,查詢語句將是無效的,語法分析器會報錯。即使錯誤提示信息沒有馬上指出錯誤是缺少了聯接條件,但最終還是可以想辦法找到問題在哪,修改好查詢語句。

    而ANSI SQL-89語法,如果忘記了指定聯接條件,查詢仍然是有效的,執行的結果集卻是一個交叉查詢

  

  ?錯誤例子?

SELECT e.empid ,e.firstname ,e.lastname ,o.orderid FROM hr.Employees AS eJOINJOIN Sales.Orders AS o錯誤:Incorrect syntax near 'o'.

?  如果使用的是ANSI SQL-89標準語法,忘記了寫連接條件,?

SELECT e.empid ,e.firstname ,e.lastname ,o.orderid FROM hr.Employees AS e ,Sales.Orders AS o

  那么恭喜得了一個大數據的大獎!爽歪歪!邏輯一復雜,錯誤在哪里也不知。

  堅持推薦使用ANSI-92的原因:

  1.是保持一致性(都有關鍵字)

  2.減少錯誤(以防邏輯條件被遺漏)

  3.提高維護性(一個寫好的存儲過程,你也不知道會被后面的人改幾次,本來是個交叉聯接改來改去成了內聯接!這個是你無法預算的,但是這是可避免,直接標明cross join.)

?

  組合聯接:就是聯接條件涉及兩邊多個列的查詢?

SELECT * FROM tabName1 AS AINNER JOIN tabName2 AS B ON A.id1 = B.idAND A.id = B.id2

?

  不等聯接:如果聯接條件只包含等號運算符,那么這樣的聯接叫做等值聯接,如果聯接條件包含除等號以外的其他運算符,那么這樣的聯接叫做不等聯接。?

SELECT * FROM tabName1 AS AINNER JOIN tabName2 AS B ON A.id1 > B.id

?

  多表聯接

    一個聯接表運算符只對兩個表進行操作,而一條查詢語句可以包含多個聯接。

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

SELECT c.custid ,c.companyname ,o.orderid ,od.productid ,od.qtyFROM Sales.Customers AS cINNER JOIN Sales.Orders AS o ON c.custid = o.custidINNER JOIN Sales.OrderDetails AS od ON o.orderid = od.orderid

?

  外聯接

    外聯接是在ANSI SQL-92中才被引入的,因此它只有一種標準語法。邏輯步驟:笛卡爾積、on過濾、添加外部行。

  在外聯接中,要把一個表標記為“保留的”表,可以在表名之間使用關鍵字 left outer join、right outer join、full outer join,其中outer關鍵字是可選的(left join 、right join、full join )。

  left關鍵字表示左邊的表的行是保留的,right關鍵字表示右邊表的行是保留的,full關鍵字則表示左右兩邊表的行都是保留的。對于來自聯接的非保留表的那些列,追加的外部行中的這些列則用null作為占位符。

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

?

  題目:查詢訂單表中所有訂單,查出從2007年1月1日到2010年12月12日之間的每個日期輸訂單個數。

DECLARE @table TABLE([num] INT NOT NULL PRIMARY KEY ,[date] DATETIME NOT NULL) SET NOCOUNT ON DECLARE @i INT= 1 BEGIN TRAN WHILE ( @i <= 3000 ) BEGININSERT INTO @table( num, date )VALUES ( @i, -- num - intDATEADD(DAY, @i - 1, '20060101') -- date - datetime ) ;SET @i = @i + 1 ;END COMMIT TRAN SET NOCOUNT OFFSELECT CAST(d.date AS DATE) AS [date] ,COUNT(o.orderid) AS [count] FROM @table AS DLEFT JOIN Sales.Orders AS O ON CAST(d.date AS DATE) = CAST(o.orderdate AS DATE) WHERE CAST(d.date AS DATE) BETWEEN '20070101'AND '20101212' GROUP BY CAST(d.date AS DATE)

  思路:

    --1 建立一個輔助表,往里面添加數據,從2006年1月1日到2014年03月17日
    --2 利用外聯接查詢

?

  ISNULL()函數

  語法

  isnull(check_expression,replacement_value) returns int

?

SELECT [date] ,ISNULL(orderid, 0) AS 'default' ,orderid FROM @table AS DLEFT JOIN Sales.Orders AS O ON CAST(d.date AS DATE) = CAST(o.orderdate AS DATE)

  圖

?

  外聯接的條件過濾

  對外聯接表中非保留表的列值進行過濾,這通常就是存在錯誤的一個標志。因為外聯接得到的外部行中的值有可能是null,而null<運算符><值>運算,得到的只會是Unknow。

  例子

?

SELECT c.custid ,c.companyname ,o.orderid ,o.orderdate FROM Sales.Customers AS CLEFT JOIN Sales.Orders AS O ON C.custid = O.custid WHERE O.orderdate >= '20070101'

  上面這條查詢語句是對Customers表和Orders表執行左聯接操作,Customers作為保留表,在where條件篩選之前,o.orderdate是有兩條為null的值使用O.orderdate >= '20070101'過濾條件后,直接將這兩條剔除了,因為null和任何比較都是unknow,而where只支持邏輯值為true的表達式,這樣的查詢條件會讓所有外部行都被過濾掉,效果上相當于抵消了外聯接的作用,換句話說,這里就是把外聯接當成內聯接用了。

?

  練習
    1-1.執行以下代碼?

SET NOCOUNT ON; USE TSQLFundamentals2008; IF OBJECT_ID('dbo.Nums','U') IS NOT NULL DROP TABLE dbo.Nums; CREATE TABLE dbo.Nums(n INT NOT NULLPRIMARY KEY)DECLARE @i INT = 1 ; BEGIN TRAN WHILE ( @i <= 100000 ) BEGININSERT INTO Nums( n )VALUES ( @i -- n - int )SET @i = @i + 1 ; END COMMIT TRAN SET NOCOUNT OFF

?

  1-2 寫一條查詢語句,把所有雇員記錄復制5次。

SELECT empid ,firstname ,lastname ,n FROM HR.Employees AS ECROSS JOIN dbo.Nums AS T WHERE n < = 5

?

  1-3 寫一個查詢,為每個雇員從2009年06月12日致2009年6月12日范圍內的每天返回一行。

SELECT H.empid ,DATEADD(DAY, n - 1, '20090101') AS [date] FROM dbo.Nums AS NCROSS JOIN HR.Employees AS H WHERE DATEADD(DAY, n - 1, '20090101') BETWEEN '20090612'AND '20090616' ORDER BY h.empid

?

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

SELECT C.custid ,COUNT(DISTINCT O.orderid)AS [count] ,SUM(OD.qty) AS totalqty FROM Sales.Customers AS CINNER JOIN Sales.Orders AS O ON C.custid = O.custidINNER JOIN Sales.OrderDetails AS OD ON O.orderid = OD.orderid WHERE C.country = 'USA' GROUP BY C.custid

?

  3.返回客戶及其訂單信息,包括沒有下過任何訂單的客戶.

SELECT c.custid ,c.companyname ,o.orderid ,o.orderdate FROM Sales.Customers AS CLEFT JOIN Sales.Orders AS O ON C.custid = O.custid

?

  4.返回在2007年02月12日下過訂單的客戶,以及他們的訂單,同時也返回在2007年2月12日沒有下過訂單的客戶.

SELECT c.custid ,c.companyname ,o.orderid ,o.orderdate FROM Sales.Customers AS CLEFT JOIN ( SELECT custid ,orderid ,orderdateFROM Sales.OrdersWHERE CAST(orderdate AS DATE) = '20070212') AS O ON C.custid = O.custid

  5.返回所有客戶信息,并根據客戶是否在2007年2月12日日下過訂單,再為每個客戶返回一列 Yes/No值。上一題的擴展。用case when

SELECT c.custid ,c.companyname ,CASE WHEN o.orderid IS NULL THEN 'No'ELSE 'Yes'END HasOrderOn20070212 FROM Sales.Customers AS CLEFT JOIN ( SELECT custid ,orderid ,orderdateFROM Sales.OrdersWHERE CAST(orderdate AS DATE) = '20070212') AS O ON C.custid = O.custid

?

轉載于:https://www.cnblogs.com/Jolinson/p/3605753.html

總結

以上是生活随笔為你收集整理的2008技术内幕:T-SQL语言基础 联接查询摘记的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。