全面解析SQL SERVER 的左右內串連,全面解析sql
SQL SERVER資料庫的三種常用串連解析:
這裡先給出一個官方的解釋:
left join(左聯結) 返回包括左表中的所有記錄和右表中連接欄位相等的記錄
right join(右聯結) 返回包括右表中的所有記錄和左表中連接欄位相等的記錄
inner join(等值串連) 只返回兩個表中連接欄位相等的行
USE [BI]
GO
DROP TABLE BI.dbo.TABLE_ONE;
GO
DROP TABLE BI.dbo.TABLE_TWO;
GO
CREATE TABLE BI.dbo.TABLE_ONE(
[ID] [int] NOT NULL,
[NAME] [nvarchar](50) NOT NULL
) ON [PRIMARY]
GO
CREATE TABLE BI.dbo.TABLE_TWO(
[ID] [int] NOT NULL,
[SCORE] [int] NOT NULL
) ON [PRIMARY]
GO
1, 如果我兩個表分別插入的是如下的資訊:
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'張三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(2,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(3,98);
GO
在這種情況下:其實左串連和右串連,內串連的結果都是一樣的:
--左串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--右串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--內串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
得到的結果都是如下:
結論:如果兩個表的記錄數是一樣的,而且主鍵的值也是一樣的話,這個時候用什麼串連他們的結果都是一樣的。
2, 如果我兩個表分別插入的是如下的資訊:
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'張三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(4,'劉六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(2,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(3,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(5,99);
GO
--左串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
返回的是左表的4條記錄,其中左邊ID=4 的在右表中存在串連的,所有右表對應的SCORE的值返回的是NULL。
--右串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 |
張三 |
90 |
2 |
李四 |
95 |
3 |
王五 |
98 |
NULL |
NULL |
99 |
返回的是右表,TABLE_TWO的4條記錄相應的記錄,其中TABLE_TWO有ID=5 的的記錄,但是TABLE_ONE裡沒有,則返回NULL。
--內串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
ID |
NAME |
SCORE |
1 |
張三 |
90 |
2 |
李四 |
95 |
3 |
王五 |
98 |
返回的是左右兩個表都有的ID:1,2,3 所以返回的是3條共有的記錄值 。
結論:如果兩個表是按照主鍵進行串連的話,左串連的話返回的記錄集肯定是等於左表返回的記錄數;右串連的話記錄集肯定是等於右表返回的記錄數;內串連就返回兩個表都存在的記錄。
上面都是以主鍵為串連條件的,對於左或右串連來說,得到的串連結果集肯定是等於串連中主表(左或右表)的記錄數的。對於內串連,則返回的是兩個表中都有的交集的記錄數。下面來介紹一下不是按照主鍵來串連的情況下,這個時候最壞的記錄數就是笛卡爾積個記錄數。
3, 如果我兩個表分別插入的是如下的資訊:
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'張三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(2,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(3,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(4,'劉六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,99);
GO
--左串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 |
張三 |
90 |
1 |
張三 |
95 |
1 |
張三 |
98 |
1 |
張三 |
99 |
2 |
李四 |
NULL |
3 |
王五 |
NULL |
4 |
劉六 |
NULL |
得出的結果集記錄數7是大於主表左邊4條記錄的。
--右串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 |
張三 |
90 |
1 |
張三 |
95 |
1 |
張三 |
98 |
1 |
張三 |
99 |
--內串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 |
張三 |
90 |
1 |
張三 |
95 |
1 |
張三 |
98 |
1 |
張三 |
99 |
4,下面就是極端的情況下,產生的是笛卡爾積。即兩個表的記錄數相乘個記錄數。
truncate table BI.DBO.TABLE_ONE;
truncate table BI.DBO.TABLE_TWO;
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'張三');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'李四');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'王五');
INSERT INTO BI.DBO.TABLE_ONE VALUES(1,'劉六');
GO
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,90);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,95);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,98);
INSERT INTO BI.DBO.TABLE_TWO VALUES(1,99);
GO
--左串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE LEFT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--右串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE RIGHT JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
--內串連
SELECT TABLE_ONE.ID,TABLE_ONE.NAME,TABLE_TWO.SCORE
FROM TABLE_ONE INNER JOIN TABLE_TWO
ON TABLE_ONE.ID=TABLE_TWO.ID;
1 |
張三 |
90 |
1 |
張三 |
95 |
1 |
張三 |
98 |
1 |
張三 |
99 |
1 |
李四 |
90 |
1 |
李四 |
95 |
1 |
李四 |
98 |
1 |
李四 |
99 |
1 |
王五 |
90 |
1 |
王五 |
95 |
1 |
王五 |
98 |
1 |
王五 |
99 |
1 |
劉六 |
90 |
1 |
劉六 |
95 |
1 |
劉六 |
98 |
1 |
劉六 |
99 |
在這種情況下得出的結果集都是14條記錄。
結論: 無論左,右串連得到的結果集的記錄數肯定是大於等於主表的記錄數的,而內串連的結果集可以是小於,等於,大於串連的表的記錄數的。
左,右還是內串連表的一個重要的用處:可以橫行的擴充一個表,可以得到一個有更多屬性的新的表。
UNION 可以縱向的增加一個表的記錄行數。
sql server 2005 中的內串連與外串連 怎理解?
舉個例子吧。
假如有學生表和班級表兩個表。
學生表 t_student
id studentname classid
1 張三 11
2 李四 12
3 王五 13
班級表 t_class
classid classname
11 高三一班
12 高三二班
可以看到,班級表中並沒有學生表中王五對應的班級的id
所以,王五是沒有對應的班級的。
如果使用內串連 也就是select * from t_student s,t_class c where s.classid = c.classid 或者
select * from t_student s inner join t_class c on s.classid = c.classid
這樣查詢出來的結果是沒有王五的。因為班級表中沒有classid是13的班級。
結果應該是
id studentname classid classname
1 張三 11 高三一班
2 李四 12 高三二班
如果使用外串連,
select * from t_student s left join t_class c on s.classid = c.classid
則可以查詢到王五,但是查詢結果中,班級對應的欄位是空白的。
結果應該是
id studentname classid classname
1 張三 11 高三一班
2 李四 12 高三二班
3 王五
通過例子,可以簡單的把內串連理解為取學生和班級的交集。兩個都有的資料,才能查詢出來。否則就查詢不出來
而外串連(例如left join)則是查詢出學生表的全部資訊以及兩個表的交集。
不知道這樣你理解了沒,如果還是不理解,就給我發郵件mazhanjun@tom.com
sqlServer內串連怎寫
內串連:
select * from A
inner join B
on 條件表達
左右串連:
分別將inner 換成left/ right 即可