交叉连接的意外结果

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会给你所有基于两个表的组合:tblEmptblDept

并且由于您使用 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 子句将简单地带走除 RichieLisan 之外的所有人,因为他们两个是唯一拥有 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