2009-08-03 7 views
3

J'ai une table qui représente une liste de pays. J'ai une autre table qui représente une liste d'états. J'ai un autre tableau qui représente une liste de provinces. En raison de la mauvaise définition des données, certains états sont réellement dans la table des provinces et vice-versa. Peu importe, chaque province et chaque état est associé à un pays.SQL - Deux jointures externes

Je dois essentiellement faire une jointure externe double gauche. Ma question est, comment puis-je faire cela? Voici ce que j'essaie actuellement:

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] 

Veuillez noter que j'ai besoin de faire quelque chose de comparable à deux jointures externes gauches. C'est une version simplifiée de la requête que j'essaie de faire. Merci de votre aide!

+0

Pouvez-vous publier des données d'échantillon et ce que vous attendez? –

+0

Notez pour les lecteurs que certains serveurs SQL tels qu'Oracle traitent une chaîne vide comme NULL. Bien qu'il semble que vous utilisiez MS SQL Server, il les traite comme prévu. c'est-à-dire dans Oracle ce serait inutile NVL (p.Name, '') ... – Matt

Répondre

3

Vous pouvez le faire comme vous l'avez indiqué. Il n'y a rien de mal à ça. Je ne remplacerais pas nécessairement les valeurs NULL avec des chaînes vides. Y a-t-il une raison pour laquelle vous faites cela? Ce que vous devez savoir lorsque vous faites ce qui sont essentiellement deux jointures un-à-plusieurs est que les résultats sont multiplicatifs. Par ceci je veux dire que si pour un pays il y a 3 entrées dans la table de province et 4 dans la table d'état vous récupérerez 12 rangées pour ce pays.

Il peut être plus approprié de faire UNION dans ces circonstances. Par exemple:

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] 

comme une seule possibilité. Cela dépend vraiment de ce à quoi ressemblent vos données et de ce que vous voulez que le résultat final soit.

2

LEFT OUTER JOIN est juste LEFT JOIN, la syntaxe est simplement:

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

Je devine que vous voulez que les provinces et les États concaténés dans une table. Pour cela, vous aurez besoin de l'opérateur syndical. J'ai également ajouté une colonne RegionType qui est 0 pour une province et 1 pour un état. Vous pouvez appliquer ce modèle pour différencier les deux dans votre requête finale.

Essayez quelque chose comme:

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 
0

alors que votre mise en œuvre couvre les États et les provinces, les territoires au sujet de ce que (par exemple le Canada a les deux, les régions et les territoires)? peut-être mieux avec une seule table pour "régions administratives" et une autre table pour les types de régions contenant "état", "province", "territoire", etc La plupart du temps, vous ne vous soucier de ce genre de région C'est juste l'identifiant du pays, l'identifiant de la région et le nom de la région.

select 
c.Name as 'CountryName', 
ISNULL(r.[Name], '') as 'RegionName' 
from 
Country c 
left outer join [Regions] r on r.[CountryID]=c.[ID] 
+0

Je ne pense pas que vous méritez la downvote, mais il ne semble pas s'inquiéter des territoires. S'il était responsable des tables, je pense que les territoires, les provinces et les États devraient tous être dans le même tableau. La distinction n'est généralement pas importante, et si c'est ... alors une colonne supplémentaire peut être ajoutée. – mpen

+1

Merci pour le soir, Mark. Je suis d'accord que le changement de schéma serait mieux comme préconisé ci-dessus. Bien sûr, le schéma actuel est juste une abstraction échouée .. s'il n'est pas trop tard pour changer, alors changez-le. Si ce n'est pas une option, alors l'option join/union proposée par cletus est un bon choix. –

0

Cela ressemble à votre problème, c'est que vous avez deux tables qui doivent être traitées comme une seule, c'est-à-dire UNION ALL. Alors que diriez-vous:

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

J'ai finalement été en mesure d'obtenir ce compris. Vous pouvez empiler autant de jointures externes que vous le souhaitez, la clé est de placer tous les qualificatifs where sur la ligne de jointure externe afin de ne pas perdre tous les zéros. Voir ci-dessous où tous les qualificatifs pour agldimension sont inclus sur la même ligne, PAS dans l'instruction 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' 
Questions connexes