SQL - два внешних соединения - PullRequest
3 голосов
/ 04 августа 2009

У меня есть таблица, которая представляет список стран. У меня есть другая таблица, которая представляет список состояний. У меня есть еще одна таблица, которая представляет список провинций. Из-за плохого определения данных некоторые штаты фактически находятся в таблице провинции и наоборот. Независимо от этого, каждая провинция и штат связаны со страной.

Мне нужно сделать двойное левое внешнее соединение. У меня вопрос, как мне это сделать? Вот что я сейчас пытаюсь:

select
  c.Name as 'CountryName',
  ISNULL(p.[Name], '') as 'ProvinceName',
  ISNULL(s.[Name], '') as 'StateName'
from
  Country c 
    left outer join [Province] p on p.[CountryID]=c.[ID]
    left outer join [State] s on s.[CountryID]=c.[ID]

Обратите внимание, что мне нужно сделать что-то сравнимое с двумя левыми внешними объединениями. Это упрощенная версия запроса, который я пытаюсь сделать. Спасибо за вашу помощь!

Ответы [ 6 ]

3 голосов
/ 04 августа 2009

Вы можете сделать это так, как вы заявили. В этом нет ничего плохого. Я бы не обязательно заменял NULL пустыми строками. Есть ли причина, по которой вы это делаете?

То, что вы должны знать при выполнении двух объединений «один ко многим», - это мультипликативные результаты. Под этим я подразумеваю, что если для страны есть 3 записи в таблице провинции и 4 в таблице состояний, вы получите 12 строк для этой страны.

В этих обстоятельствах было бы более уместно сделать СОЮЗ. Например:

SELECT
  c.Name AS 'CountryName',
  '' AS 'ProvinceName',
  ISNULL(s.[Name], '') AS 'StateName'
FROM Country c 
LEFT OUTER JOIN [Province] p ON p.[CountryID]=c.[ID]
UNION ALL
SELECT
  c.Name AS 'CountryName',
  ISNULL(p.[Name], '') AS 'ProvinceName',
  '' AS 'ProvinceName'
FROM Country c 
LEFT OUTER JOIN [State] s ON s.[CountryID]=c.[ID]

только одна возможность. Это действительно зависит от того, как выглядят ваши данные и каков будет конечный результат.

2 голосов
/ 04 августа 2009

LEFT OUTER JOIN - это просто LEFT JOIN, синтаксис просто:

SELECT c.Name AS CountryName
p.Name AS ProvinceName
s.Name AS StateName
FROM Country c
LEFT JOIN Province p ON p.CountryID = c.ID
LEFT JOIN State s ON s.CountryID = c.ID
0 голосов
/ 05 июня 2013

Я наконец смог выяснить это. Вы можете сложить столько внешних объединений, сколько хотите, ключ в том, чтобы поместить все квалификаторы where на внешнюю линию соединения, чтобы не потерять все пустые значения. См. Ниже, где все квалификаторы agldimension включены в одну строку, а НЕ в оператор where.

select distinct
act.account, 
act.[description],
rul.[description],
att1.att_name,
att2.att_name,
att3.att_name,
att4.att_name,
att5.att_name,
att6.att_name,
att7.att_name
from aglaccounts act, aglrules rul  
full outer join agldimension att1 on rul.att_1_id = att1.attribute_id and att1.[status] = 'N' and att1.client = 'PH' 
full outer join agldimension att2 on rul.att_2_id = att2.attribute_id and att2.[status] = 'N' and att2.client = 'PH'
full outer join agldimension att3 on rul.att_3_id = att3.attribute_id and att3.[status] = 'N' and att3.client = 'PH'
full outer join agldimension att4 on rul.att_4_id = att4.attribute_id and att4.[status] = 'N' and att4.client = 'PH'
full outer join agldimension att5 on rul.att_5_id = att5.attribute_id and att5.[status] = 'N' and att5.client = 'PH'
full outer join agldimension att6 on rul.att_6_id = att6.attribute_id and att6.[status] = 'N' and att6.client = 'PH'
full outer join agldimension att7 on rul.att_7_id = att7.attribute_id and att7.[status] = 'N' and att7.client = 'PH'
where 
act.account_rule = rul.account_rule and act.client = 'PH' and act.[status] = 'N'
0 голосов
/ 04 августа 2009

Похоже, ваша проблема в том, что у вас есть две таблицы, которые нужно рассматривать как одну, то есть UNION ALL. Так как насчет:

SELECT 
    c.Name as Country
   ,ps.Name as StateOrProvince
FROM        Country c
LEFT JOIN   (SELECT CountryID, Name FROM Province UNION ALL SELECT CountryID, Name FROM State) ps
    ON ps.CountryID = c.ID
;

Rob

0 голосов
/ 04 августа 2009

в то время как ваша реализация охватывает штаты и провинции, а как насчет территорий (например, в Канаде есть как регионы, так и территории)? может быть лучше использовать одну таблицу для «административных регионов» и другую таблицу для типов регионов, содержащих «штат», «провинция», «территория» и т. д. Большую часть времени вас не волнует, что это за регион, только идентификатор страны, идентификатор региона и название региона.

select
c.Name as 'CountryName',
ISNULL(r.[Name], '') as 'RegionName'
from
Country c 
left outer join [Regions] r on r.[CountryID]=c.[ID]
0 голосов
/ 04 августа 2009

Полагаю, вы хотите объединить провинции и штаты в одну таблицу. Для этого вам понадобится оператор объединения. Я также добавил столбец RegionType, который равен 0 для провинции и 1 для штата. Возможно, вы захотите применить этот шаблон для разграничения между ними в вашем последнем запросе.

Попробуйте что-то вроде:

SELECT c.Name as CountryName, p.Name as RegionName, 0 as RegionType
FROM Country c
LEFT OUTER JOIN Province p on c.ID = p.CountryID
UNION ALL
SELECT c.Name as CountryName, s.Name as RegionName, 1 as RegionType
FROM Country c
LEFT OUTER JOIN State s on s.ID = p.CountryID
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...