前言
本節(jié)開始我們進(jìn)入聯(lián)接學(xué)習(xí),關(guān)于連接這一塊涉及的內(nèi)容比較多,我們一步一步循序漸進(jìn)學(xué)習(xí),簡(jiǎn)短內(nèi)容,深入的理解。
交叉聯(lián)接(CROSS JOIN)
交叉連接是最簡(jiǎn)單的聯(lián)接類型。交叉聯(lián)接僅執(zhí)行一個(gè)邏輯查詢處理階段-笛卡爾乘積。例如對(duì)兩個(gè)輸入表進(jìn)行操作,聯(lián)接并生成兩個(gè)表的笛卡爾乘積,也就是說(shuō),將一個(gè)表的每一行與另一個(gè)表的所有行進(jìn)行匹配。所以,如果一個(gè)表有m行,另一個(gè)表有n行,得到的結(jié)果中則會(huì)有m*n行。我們就拿SQL Server 2012教程中的例子說(shuō)下
SELECT C.custid, E.empid
FROM Sales.Customers AS C
CROSS JOIN HR.Employees AS E
ORDER BY E.empid
在Sales.Customers表中有91行數(shù)據(jù),HR.Employees表中有9行數(shù)據(jù),則利用交叉聯(lián)接數(shù)據(jù)則有819(91*9)行數(shù)據(jù),簡(jiǎn)略數(shù)據(jù)如下。
![](/d/20211017/c6501faf4d9d72ff918df4d61575136e.gif)
交叉聯(lián)接我們可以用如下圖表示
![](/d/20211017/0374fab9343df7131723a7e27bdaed1b.gif)
交叉聯(lián)接最大的用途在于生成數(shù)字表以便我們用于其他目的,我們一起來(lái)看看。
IF OBJECT_ID('dbo.Digits','U')
IS NOT NULL DROP TABLE dbo.Digits;
CREATE TABLE dbo.Digits
(
digit INT NOT NULL
);
插入10條基礎(chǔ)數(shù)據(jù)
USE TSQL2012
GO
INSERT INTO dbo.Digits
( digit )
VALUES ( 0 ), ( 1 ), ( 2 ), ( 3 ), ( 4 ), ( 5 ), ( 6 ), ( 7 ), ( 8 ), ( 9 )
創(chuàng)建數(shù)字表
USE TSQL2012
GO
CREATE TABLE Nums
(
n INT NOT NULL PRIMARY KEY
);
利用交叉聯(lián)接在數(shù)字表中插入100萬(wàn)條數(shù)據(jù)
USE TSQL2012
GO
INSERT INTO dbo.Nums(n)
SELECT D6.digit * 100000 + D5.digit * 10000 + D4.digit * 1000 + D3.digit * 100 + D2.digit * 10 + D1.digit + 1 AS n
FROM dbo.Digits AS D1
CROSS JOIN dbo.Digits AS D2
CROSS JOIN dbo.Digits AS D3
CROSS JOIN dbo.Digits AS D4
CROSS JOIN dbo.Digits AS D5
CROSS JOIN dbo.Digits AS D6
ORDER BY n
![](/d/20211017/016fd6c004e35912da14b3e7522a32b9.gif)
內(nèi)部聯(lián)接(INNER JOIN)
內(nèi)部聯(lián)接用法如下
SELECT *
FROM table1 AS t1
INNER JOIN table2 AS t2 ON t1.Id = t2.Id
內(nèi)部聯(lián)接返回表中更多數(shù)據(jù)
我們首先給出如下三個(gè)測(cè)試表
USE TSQL2012
GO
CREATE TABLE FirstTable (Col1 INT)
CREATE TABLE SecondTable (Col1 INT)
CREATE TABLE ThirdTable (Col1 INT)
GO
INSERT INTO FirstTable (Col1)
VALUES (1), (2), (3), (NULL)
GO
INSERT INTO SecondTable (Col1)
VALUES (1), (2), (3), (NULL)
GO
INSERT INTO ThirdTable (Col1)
VALUES (2), (2), (2), (2), (2), (NULL)
GO
(1)等值條件查詢
SELECT f.Col1 fCol1
FROM FirstTable f
INNER JOIN SecondTable s ON s.Col1 = f.col1
GO
![](/d/20211017/d0d7471518d96f47e08ecdf349f7bee7.gif)
(2)非等值條件查詢
USE TSQL2012
GO
SELECT f.Col1 fCol1
FROM FirstTable f
INNER JOIN SecondTable s ON s.Col1 > f.col1
GO
![](/d/20211017/b211fe9a98cd060fc42e462f14e80477.gif)
上述我們同樣可以利用交叉連接實(shí)現(xiàn)同樣效果
USE TSQL2012
GO
SELECT f.Col1 fCol1
FROM FirstTable AS f
CROSS JOIN SecondTable AS s
where s.Col1 > f.col1
GO
(3)查詢非重復(fù)行(NON-DISTINCT)
我們?cè)趧?chuàng)建第三個(gè)測(cè)試表時(shí),插入的數(shù)據(jù)是5個(gè)2,而在第一個(gè)表中插入的數(shù)據(jù)分別是1、2、3,此時(shí)我們利用等值聯(lián)接得到的結(jié)果到底是1個(gè)2,還是5個(gè)2呢?
USE TSQL2012
GO
SELECT f.Col1 fCol1
FROM FirstTable f
INNER JOIN ThirdTable s ON s.Col1 = f.col1
GO
![](/d/20211017/02a37686898b6dccf035513d1589da5d.gif)
我們得到的結(jié)果是5個(gè)2,為什么利用內(nèi)部聯(lián)接也就是說(shuō)利用的等值條件不是返回1個(gè)2呢,其實(shí)我們可以總結(jié)如下:
結(jié)論:利用內(nèi)部聯(lián)接比實(shí)際表中返回更多數(shù)據(jù)的原因在于,內(nèi)部聯(lián)接返回的結(jié)果集是基于查詢條件中的JOIN,若有多行滿足條件則返回多條數(shù)據(jù)。
內(nèi)部聯(lián)接安全性
在兩個(gè)表利用等值條件查詢時(shí),我們有兩種寫法。
ANSI SQL-92寫法
USE TSQL2012
GO
SELECT *
FROM Sales.Orders AS SO
INNER JOIN Sales.OrderDetails AS SOD ON SOD.orderid = SO.orderid
ANSI SQL-89寫法
USE TSQL2012
GO
SELECT *
FROM Sales.Orders AS SO, Sales.OrderDetails AS SOD
WHERE SOD.orderid = SO.orderid
雖然這兩種寫法都可以,都能滿足需求,但是SQL Server 2012基礎(chǔ)教程強(qiáng)烈建議使用ANSI SQL-92寫法,為什么呢,因?yàn)橛肁NSI SQL-89寫法時(shí)若出現(xiàn)錯(cuò)誤,此時(shí)解析根本不會(huì)生成錯(cuò)誤,而對(duì)于ANSI SQL-92寫法則會(huì),下面我們一起來(lái)看下ANSI SQL-89寫法的問(wèn)題
USE TSQL2012
GO
SELECT COUNT(*) AS '利用等值條件查詢總數(shù)據(jù)行'
FROM Sales.Orders AS SO, Sales.OrderDetails AS SOD
WHERE SOD.orderid = SO.orderid
![](/d/20211017/2d9f4528e86521f4fac6e848b9fb6fee.gif)
上面是我們利用正確的寫法得到的正確的總數(shù)據(jù)行為2155條,下面我們看看有問(wèn)題的寫法
SELECT COUNT(*) AS '利用等值條件查詢總數(shù)據(jù)行'
FROM Sales.Orders AS SO, Sales.OrderDetails AS SOD
![](/d/20211017/7dc88d34812fc7f0bc2e253f0a051ee0.gif)
此時(shí)我們沒(méi)有給出WHERE條件,而解析未出現(xiàn)錯(cuò)誤,當(dāng)然返回的結(jié)果集也就是錯(cuò)誤的。當(dāng)我們利用ANSI SQL-92寫法時(shí),我們同樣也未給出比較條件,如下
USE TSQL2012
GO
SELECT *
FROM Sales.Orders AS SO
INNER JOIN Sales.OrderDetails AS SOD;
![](/d/20211017/776c72c90f8e54127fa2a18ddc176afa.gif)
此時(shí)會(huì)出現(xiàn)解析錯(cuò)誤,也就是無(wú)法再繼續(xù)查詢,自然也就得不到錯(cuò)誤的結(jié)果。
結(jié)論:強(qiáng)烈推薦使用ANSI SQL-92寫法,這樣一來(lái)使得數(shù)據(jù)不會(huì)出現(xiàn)不一致性,同時(shí)可讀性和可維護(hù)性比ANSI SQL-89寫法強(qiáng)。
總結(jié)
本節(jié)我們講了交叉聯(lián)接和內(nèi)部聯(lián)接,同時(shí)也給出了使用需要注意的地方,本節(jié)到此結(jié)束,我們下節(jié)再講講自聯(lián)接和外部聯(lián)接。簡(jiǎn)短的內(nèi)容,深入的理解,我們下節(jié)再會(huì),good night。
以上就是本文的全部?jī)?nèi)容,希望本文的內(nèi)容對(duì)大家的學(xué)習(xí)或者工作能帶來(lái)一定的幫助,如果有疑問(wèn)大家可以留言交流,同時(shí)也希望多多支持腳本之家!
您可能感興趣的文章:- SQL Server 2005通用分頁(yè)存儲(chǔ)過(guò)程及多表聯(lián)接應(yīng)用
- SQL設(shè)置SQL Server最大連接數(shù)及查詢語(yǔ)句
- 解析SQL Server聚焦移除(Bookmark Lookup、RID Lookup、Key Lookup)
- 詳解SQL Server的聚焦過(guò)濾索引
- 淺述SQL Server的聚焦強(qiáng)制索引查詢條件和Columnstore Index
- 淺析SQL Server的分頁(yè)方式 ISNULL與COALESCE性能比較
- 詳解SQL Server中的數(shù)據(jù)類型
- 淺析SQL Server的聚焦使用索引和查詢執(zhí)行計(jì)劃
- 淺析SQL Server 聚焦索引對(duì)非聚集索引的影響
- 如何快速刪掉SQL Server登錄時(shí)登錄名下拉列表框中的選項(xiàng)