当嵌套select具有临时表时,如何将嵌套选择转换为连接?

时间:2009-10-27 10:36:51

标签: sql sql-server sql-server-2008

我有以下SQL。表定义。

#tbContinent 
--------
ContinentID | ContinentName 

AddressInCountry
--------
AddressID | CountryID

AddressInContinent
--------
AddressID | ContinentID

NameInAddress
--------
AddressID | NameID

然后我有以下SQL:

---     Insert into tbName
DECLARE @tbName TABLE 
([ID] int, [AddressID] int, [Name] ntext)

INSERT INTO @tbName 
SELECT 
    [Name].[NameID] AS [ID],
    [Address].[AddressID],
    [Name].[Name]
    FROM NameInAddress INNER JOIN [Name] ON NameInAddress.NameID = Name.NameID
    INNER JOIN [Address] ON NameInAddress.AddressID = Address.AddressID


WHERE [Address].[AddressID] IN
(
    SELECT  AddressInCountry.AddressID
        FROM AddressInCountry 
    UNION ALL
    SELECT  AddressInContinent.AddressID
        FROM #tbContinent AS Continent
        JOIN AddressInContinent ON Continent.ContinentID = AddressInContinent.ContinentID    
) 

我被要求使用连接代替嵌套选择。 我已经使用视图来创建联盟并在视图上执行联接, 但是这个使用临时表我无法传递到我的视图中所以不要以为我可以使用相同的技术。

我根本不能使用嵌套选择。

有什么想法吗?

2 个答案:

答案 0 :(得分:2)

让我们再回答一下。

查看集合论/关系代数,由WHERE EXISTS调用完成的操作称为LEFT SEMI JOIN(并且NOT EXISTS是LEFT ANTI SEMI JOIN)。这意味着连接仅用作过滤器,它不会引入额外的字段,也不会导致左表中的数据重复。

要实现不带EXISTS的半连接,您可以执行内部联接,确保右表中没有重复项,就像在我的其他答案中一样。

当您想要提取UNION ALL时,您需要将其他连接逻辑放在带有union的第一部分的查询中,然后在第二部分中复制该逻辑。

但是,半连接不会重复左边的条目意味着您需要查看重复项,但仍然会以某种方式包含原始版本中可能存在的重复项。

老实说,这里正确的方法是使用子查询,而WHERE EXISTS是实现Left Semi Join的理想方法。

答案 1 :(得分:0)

JOIN 
(
    SELECT  AddressInCountry.AddressID
    FROM AddressInCountry 
    UNION --ALL
    SELECT  AddressInContinent.AddressID
    FROM #tbContinent AS Continent
    JOIN AddressInContinent ON Continent.ContinentID = AddressInContinent.ContinentID        
) AS aic
ON aic.AddressID = [Address].[AddressID]

我建议UNION over UNION ALL,因为你不需要重复的条目(以匹配EXISTS功能)。