Как преобразовать вложенный выбор в объединения, если у вложенного выбора есть временная таблица? - PullRequest
1 голос
/ 27 октября 2009

У меня есть следующий 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 ]

2 голосов
/ 28 октября 2009

Давайте еще раз попробуем ответить.

Глядя на теорию множеств / реляционную алгебру, операция, выполняемая вызовом WHERE EXISTS, называется LEFT SEMI JOIN (а NOT EXISTS - это LEFT ANTI SEMI JOIN). Это означает, что объединение используется только как фильтр, оно не извлекает дополнительные поля и не вызывает дублирования данных в левой таблице.

Чтобы реализовать полусоединение без EXISTS, вы можете выполнить внутреннее объединение, убедившись, что в правой таблице нет дубликатов, как в моем другом ответе.

Поскольку вы хотите извлечь UNION ALL, вам нужно будет поместить другую логику соединения в запрос с первой частью объединения, а затем продублировать эту логику во второй.

Но тогда тот факт, что полусоединение не дублирует записи слева, означает, что вам нужно следить за дубликатами, но все равно каким-то образом включать дубликаты, которые могут быть в исходной версии.

Честно говоря, правильным подходом здесь является использование подзапроса, и ГДЕ СУЩЕСТВУЕТ - это идеальный способ реализовать левое полусоединение.

0 голосов
/ 27 октября 2009
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 вместо UNION ALL здесь, потому что вы не хотите дублировать записи (чтобы соответствовать функциональности EXISTS).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...