交叉连接的意外结果
Unexpected result of Cross join
这些是我的 tblEmp table 和 tblDept table(我正在使用 MS-SQL Server 2012), 当我尝试在这两个 tables 上使用交叉连接时,它给了我我没想到的结果,只是想知道为什么这个交叉连接会给出这种结果,谢谢你.
ID Name Gender Salary Dept_id
1 abc male 2004 1
2 Tom female 5004 2
3 Sara female 29404 2
4 Jim male 8604 3
5 Lisan male 2078 1
6 Brad male 9804 3
7 Diana female 2095 2
8 Henry male 28204 2
9 Mark male 20821 1
10 Miley female 9456 1
11 Richie male 8604 NULL
12 Lisan female 20776 NULL
tblDept
ID Dept_Name Location
1 IT Mumbai
2 HR Delhi
3 Accounts London
4 OtherDepartment NewYork
这是交叉连接查询及其输出
select Name, Gender, Salary, Dept_Name
from tblEmp
CROSS JOIN tblDept
where tblEmp.Dept_id is NULL
输出
Name Gender Salary Dept_Name
Richie male 8604 IT
Richie male 8604 HR
Richie male 8604 Accounts
Richie male 8604 OtherDepartment
Lisan female 20776 IT
Lisan female 20776 HR
Lisan female 20776 Accounts
Lisan female 20776 OtherDepartment
我期待的是这样的
Name Gender Salary Dept_Name
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
A CROSS JOIN
会给你第一个 table 的每一行与第二个 table 的每一行的连接(笛卡尔积),除非你使用 where 添加条件连接两个 table 的子句(在这种情况下,它的行为类似于内部联接)
下面是交叉连接的快速演示:
DECLARE @A table
(
A1 int identity(1,1),
A2 int
)
DECLARE @B table
(
B1 int identity(1,1),
B2 int
)
INSERT INTO @A VALUES (1), (2), (NULL)
INSERT INTO @B VALUES (4), (5), (6)
SELECT *
FROM @A
CROSS JOIN @B
结果:
A1 A2 B1 B2
----------- ----------- ----------- -----------
1 1 1 4
2 2 1 4
3 NULL 1 4
1 1 2 5
2 2 2 5
3 NULL 2 5
1 1 3 6
2 2 3 6
3 NULL 3 6
如您所见,对于 table @A 中的每条记录,您加入了 table @B
中的每条记录
SELECT *
FROM @A
CROSS JOIN @B
WHERE A2 IS NULL
结果:
A1 A2 B1 B2
----------- ----------- ----------- -----------
3 NULL 1 4
3 NULL 2 5
3 NULL 3 6
如您所见,对于 table @A 中 A2 为空的每条记录,您加入 table @B 的每条记录。
结果是正确的,cross join
会给你所有基于两个表的组合:tblEmp
和tblDept
。
并且由于您使用 Dept_Name
作为组合,没有 where 子句,它将为您提供两个表之间可能的所有组合:
Name Gender Salary Dept_Name
abc male 2004 IT
abc male 2004 HR
abc male 2004 Accounts
abc male 2004 OtherDepartment
Tom female 5004 IT
Tom female 5004 HR
Tom female 5004 Accounts
Tom female 5004 OtherDepartment
... and so on
Richie male 8604 IT
Richie male 8604 HR
Richie male 8604 Accounts
Richie male 8604 OtherDepartment
Lisan female 20776 IT
Lisan female 20776 HR
Lisan female 20776 Accounts
Lisan female 20776 OtherDepartment
也就是说,通过交叉连接,您实际上会得到 12(来自 tblEmp
)x 4(来自 tblDept
)= 48 行
那么你的 where 子句将简单地带走除 Richie
和 Lisan
之外的所有人,因为他们两个是唯一拥有 Dept_id = NULL
的人
Name Gender Salary Dept_Name
Richie male 8604 IT
Richie male 8604 HR
Richie male 8604 Accounts
Richie male 8604 OtherDepartment
Lisan female 20776 IT
Lisan female 20776 HR
Lisan female 20776 Accounts
Lisan female 20776 OtherDepartment
如果您也查询 Dept_id
列,
select Name, Gender, Salary, Dept_id, Dept_Name
from tblEmp
CROSS JOIN tblDept
where tblEmp.Dept_id is NULL
结果会更清楚,因为你实际上只得到 Dept_id = NULL
:
的员工
Name Gender Salary Dept_id Dept_Name
Richie male 8604 NULL IT
Richie male 8604 NULL HR
Richie male 8604 NULL Accounts
Richie male 8604 NULL OtherDepartment
Lisan female 20776 NULL IT
Lisan female 20776 NULL HR
Lisan female 20776 NULL Accounts
Lisan female 20776 NULL OtherDepartment
您的 Dept_Name
列来自 4 tblDept
个条目,而不是 tblEmp
个条目。
如果你需要显示所有员工和他们的部门,你可以使用 LEFT JOIN:
SELECT Name, Gender, Salary, Dept_Name
FROM
tblEmp AS E
LEFT JOIN
tblDept AS D
ON E.Dept_id = D.ID
结果:
Name Gender Salary Dept_Name
abc male 2004 IT
Tom female 5004 HR
Sara female 29404 HR
Jim male 8604 Accounts
Lisan male 2078 IT
Brad male 9804 Accounts
Diana female 2095 HR
Henry male 28204 HR
Mark male 20821 IT
Miley female 9456 IT
Richie male 8604 NULL
Lisan female 20776 NULL
或
如果需要显示所有员工和所有部门,可以使用FULL JOIN:
SELECT Name, Gender, Salary, Dept_Name
FROM
tblEmp AS E
FULL JOIN
tblDept AS D
ON E.Dept_id = D.ID
结果:
Name Gender Salary Dept_Name
abc male 2004 IT
Tom female 5004 HR
Sara female 29404 HR
Jim male 8604 Accounts
Lisan male 2078 IT
Brad male 9804 Accounts
Diana female 2095 HR
Henry male 28204 HR
Mark male 20821 IT
Miley female 9456 IT
Richie male 8604 NULL
Lisan female 20776 NULL
NULL NULL NULL OtherDepartment
如果您确实希望每个部门的每个人都有一个空行 dept_id 例如
Name Gender Salary Dept_Name
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
你可以执行这个...
select Name, Gender, Salary, NULL AS Dept_Name
from tblEmp
CROSS JOIN tblDept
where tblEmp.Dept_id is NULL
这些是我的 tblEmp table 和 tblDept table(我正在使用 MS-SQL Server 2012), 当我尝试在这两个 tables 上使用交叉连接时,它给了我我没想到的结果,只是想知道为什么这个交叉连接会给出这种结果,谢谢你.
ID Name Gender Salary Dept_id
1 abc male 2004 1
2 Tom female 5004 2
3 Sara female 29404 2
4 Jim male 8604 3
5 Lisan male 2078 1
6 Brad male 9804 3
7 Diana female 2095 2
8 Henry male 28204 2
9 Mark male 20821 1
10 Miley female 9456 1
11 Richie male 8604 NULL
12 Lisan female 20776 NULL
tblDept
ID Dept_Name Location
1 IT Mumbai
2 HR Delhi
3 Accounts London
4 OtherDepartment NewYork
这是交叉连接查询及其输出
select Name, Gender, Salary, Dept_Name
from tblEmp
CROSS JOIN tblDept
where tblEmp.Dept_id is NULL
输出
Name Gender Salary Dept_Name
Richie male 8604 IT
Richie male 8604 HR
Richie male 8604 Accounts
Richie male 8604 OtherDepartment
Lisan female 20776 IT
Lisan female 20776 HR
Lisan female 20776 Accounts
Lisan female 20776 OtherDepartment
我期待的是这样的
Name Gender Salary Dept_Name
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
A CROSS JOIN
会给你第一个 table 的每一行与第二个 table 的每一行的连接(笛卡尔积),除非你使用 where 添加条件连接两个 table 的子句(在这种情况下,它的行为类似于内部联接)
下面是交叉连接的快速演示:
DECLARE @A table
(
A1 int identity(1,1),
A2 int
)
DECLARE @B table
(
B1 int identity(1,1),
B2 int
)
INSERT INTO @A VALUES (1), (2), (NULL)
INSERT INTO @B VALUES (4), (5), (6)
SELECT *
FROM @A
CROSS JOIN @B
结果:
A1 A2 B1 B2
----------- ----------- ----------- -----------
1 1 1 4
2 2 1 4
3 NULL 1 4
1 1 2 5
2 2 2 5
3 NULL 2 5
1 1 3 6
2 2 3 6
3 NULL 3 6
如您所见,对于 table @A 中的每条记录,您加入了 table @B
中的每条记录SELECT *
FROM @A
CROSS JOIN @B
WHERE A2 IS NULL
结果:
A1 A2 B1 B2
----------- ----------- ----------- -----------
3 NULL 1 4
3 NULL 2 5
3 NULL 3 6
如您所见,对于 table @A 中 A2 为空的每条记录,您加入 table @B 的每条记录。
结果是正确的,cross join
会给你所有基于两个表的组合:tblEmp
和tblDept
。
并且由于您使用 Dept_Name
作为组合,没有 where 子句,它将为您提供两个表之间可能的所有组合:
Name Gender Salary Dept_Name
abc male 2004 IT
abc male 2004 HR
abc male 2004 Accounts
abc male 2004 OtherDepartment
Tom female 5004 IT
Tom female 5004 HR
Tom female 5004 Accounts
Tom female 5004 OtherDepartment
... and so on
Richie male 8604 IT
Richie male 8604 HR
Richie male 8604 Accounts
Richie male 8604 OtherDepartment
Lisan female 20776 IT
Lisan female 20776 HR
Lisan female 20776 Accounts
Lisan female 20776 OtherDepartment
也就是说,通过交叉连接,您实际上会得到 12(来自 tblEmp
)x 4(来自 tblDept
)= 48 行
那么你的 where 子句将简单地带走除 Richie
和 Lisan
之外的所有人,因为他们两个是唯一拥有 Dept_id = NULL
Name Gender Salary Dept_Name
Richie male 8604 IT
Richie male 8604 HR
Richie male 8604 Accounts
Richie male 8604 OtherDepartment
Lisan female 20776 IT
Lisan female 20776 HR
Lisan female 20776 Accounts
Lisan female 20776 OtherDepartment
如果您也查询 Dept_id
列,
select Name, Gender, Salary, Dept_id, Dept_Name
from tblEmp
CROSS JOIN tblDept
where tblEmp.Dept_id is NULL
结果会更清楚,因为你实际上只得到 Dept_id = NULL
:
Name Gender Salary Dept_id Dept_Name
Richie male 8604 NULL IT
Richie male 8604 NULL HR
Richie male 8604 NULL Accounts
Richie male 8604 NULL OtherDepartment
Lisan female 20776 NULL IT
Lisan female 20776 NULL HR
Lisan female 20776 NULL Accounts
Lisan female 20776 NULL OtherDepartment
您的 Dept_Name
列来自 4 tblDept
个条目,而不是 tblEmp
个条目。
如果你需要显示所有员工和他们的部门,你可以使用 LEFT JOIN:
SELECT Name, Gender, Salary, Dept_Name
FROM
tblEmp AS E
LEFT JOIN
tblDept AS D
ON E.Dept_id = D.ID
结果:
Name Gender Salary Dept_Name
abc male 2004 IT
Tom female 5004 HR
Sara female 29404 HR
Jim male 8604 Accounts
Lisan male 2078 IT
Brad male 9804 Accounts
Diana female 2095 HR
Henry male 28204 HR
Mark male 20821 IT
Miley female 9456 IT
Richie male 8604 NULL
Lisan female 20776 NULL
或
如果需要显示所有员工和所有部门,可以使用FULL JOIN:
SELECT Name, Gender, Salary, Dept_Name
FROM
tblEmp AS E
FULL JOIN
tblDept AS D
ON E.Dept_id = D.ID
结果:
Name Gender Salary Dept_Name
abc male 2004 IT
Tom female 5004 HR
Sara female 29404 HR
Jim male 8604 Accounts
Lisan male 2078 IT
Brad male 9804 Accounts
Diana female 2095 HR
Henry male 28204 HR
Mark male 20821 IT
Miley female 9456 IT
Richie male 8604 NULL
Lisan female 20776 NULL
NULL NULL NULL OtherDepartment
如果您确实希望每个部门的每个人都有一个空行 dept_id 例如
Name Gender Salary Dept_Name
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Richie male 8604 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
Lisan female 20776 NULL
你可以执行这个...
select Name, Gender, Salary, NULL AS Dept_Name
from tblEmp
CROSS JOIN tblDept
where tblEmp.Dept_id is NULL