避免SQL Server中的交叉连接

时间:2018-06-08 20:34:19

标签: sql-server sql-server-2008 sql-server-2005 sql-server-2012 cross-join

我有两张桌子T1和T2。

T1

ID  |   Name                              
----+-------
A   |   A1                                
A   |   C1

T2

ID   | Name
-----+------
A    | A1
A    | B1

我想检索具有相同ID和Name的记录,其中包含标志1和相同ID以及具有标志0的不同名称。但是,在SQL Server中加入表时,我得到的是交叉连接:

A | A1 | A1 | 1                 
A | A1 | B1 | 0  
A | C1 | A1 | 0  
A | C1 | B1 | 0

但我需要答案为:

A | A1 | A1 | 1     
A | C1 | B1 | 0

上述结果为我提供了有关名称不匹配的相同信息,但在有限的情况下。行,没有重复。

有人可以告诉我如何在SQL Server中执行此操作吗?

3 个答案:

答案 0 :(得分:0)

这就是你所追求的:

SELECT T1.ID, T1.Name Name1, T2.Name Name2, case T1.Name when T2.Name then 1 else 0 end Result
from T1
inner join T2 on T1.ID = T2.ID
where T1.Name = T2.Name
    or (not exists (select 1 from T2 where T1.Name = Name and T1.ID = ID)
        and not exists (select 1 from T1 where T2.Name = Name and T2.ID = ID))

答案 1 :(得分:0)

使用联合来保持简单:

select T1.ID, T1.Name Name1, T2.Name Name2, 1 flag
from T1
join T2 on T1.ID = T2.ID
and T1.Name = T2.Name
union all
select T1.ID, T1.Name, T2.Name, 0
from T1
join T2 on T1.ID = T2.ID
and T1.Name != T2.Name

使用union不是 最有效的方法,但它更容易理解,除非你有数百万行,它仍然会非常快地运行(并union all非常比union)快一点

答案 2 :(得分:0)

您可以使用ROW_NUMBERFULL JOIN

DECLARE @T1 TABLE (ID VARCHAR(5),   Name VARCHAR(5))
INSERT INTO @T1 VALUES ('A', 'A1')
INSERT INTO @T1 VALUES('A', 'C1')

DECLARE @T2 TABLE (ID VARCHAR(5),   Name VARCHAR(5))
INSERT INTO @T2 VALUES ('A', 'A1')
INSERT INTO @T2 VALUES ('A', 'B1')


SELECT T1.ID, T1.Name, T2.Name, CASE WHEN T1.Name = T2.Name THEN 1 ELSE 0 END
FROM 
    ( SELECT ROW_NUMBER()OVER(PARTITION BY ID ORDER BY Name) AS RN, * FROM @T1 ) T1
    FULL JOIN 
    ( SELECT ROW_NUMBER()OVER(PARTITION BY ID ORDER BY Name) AS RN, * FROM @T2 ) T2 
        ON T1.ID = T2.ID AND T1.RN = T2.RN

结果:

ID    Name  Name  
----- ----- ----- -----------
A     A1    A1    1
A     C1    B1    0