2010-12-06 5 views
1

Je suis confronté à un problème de jointure dans la base de données SQL Server 2005. J'ai la structure des tableaux suivants:SQL Server: comment faire une requête avec une jointure externe gauche + jointure interne dépendante?

TableA --LEFT JOIN--> TableB --INNER JOIN-->TableC 

Donc, si j'écris une requête comme ceci:

SELECT TableA.* FROM TableA 
LEFT OUTER JOIN TableB ON TableA.keyOfB = TableB.key 
INNER JOIN TableC ON TableB.keyOfC = TableC.key 
where TableA.key = aValue 

il lu 0 enregistrement s'il n'y a aucun enregistrement TableB associé à TableA enregistrement. Mais TableB est dans la jointure externe, donc ce n'est pas ce que j'attendais. En d'autres termes, le INNER JOIN n'aurait pas dû être considéré, car il n'y a aucun enregistrement TableB! Qu'est-ce qui me manque?

Répondre

1

Je pense qu'il a à voir avec l'ordre de se joindre aux opérations. Le résultat de (UNE JOINTE JOINTE B B) INNER JOIN C, vous voulez une gauche extérieure (BINNER JOIN C).

Essayez d'y déposer quelques().

Ou essayez réorganisant votre REJOINT ... B INNER C OUTER A pour obtenir (B INNER C) OUTER A.

EDIT: Exemple de ce que je pensais:

SELECT TableA.* FROM TableA 
LEFT OUTER JOIN (TableB INNER JOIN TableC ON TableB.keyOfC = TableC.key) 
ON TableA.keyOfB = TableB.key 
WHERE TableA.key = aValue 

Retournement à OUTER:

SELECT TableA.* FROM TableB 
INNER JOIN TableC ON TableB.keyOfC = TableC.key 
RIGHT OUTER JOIN TableA ON TableA.keyOfB = TableB.key 
WHERE TableA.key = aValue 

REMARQUE: Pardonnez-moi si cela est ne fonctionne pas, je ne l'ai pas touché SqlServer depuis la version 7.

1

Utilisez une table virtuelle pour la jointure (B + C).
EDIT: Quelque chose comme:

SELECT TableA.* FROM TableA 
LEFT OUTER JOIN 
    (select key from TableB INNER JOIN TableC ON TableB.keyOfC = TableC.key) as TableBC 
    ON TableA.keyOfB = TableBC.key 
where TableA.key = aValue 
+0

Pouvez-vous modifier le code de Pier Luigi avec votre suggestion parce que je ne suis pas sûr de ce que vous voulez dire ici? – David

+0

+1 - Je n'ai pas vraiment compris ce que l'OP avait besoin au début mais je pense que cela va à l'essentiel. Une fois groupé comme vous le suggérez, seul l'Enregistrement A est 'nécessaire', les champs de B et C suivront s'ils BATTENT. –

+0

Ce n'est pas aussi simple que d'ajouter quelques parenthèses, il faut un peu de réorganisation et probablement un nouveau SELECT, sauf s'il y a quelque chose d'intelligent im manquant (toujours très possible = P) –

1

Ce se comporte exactement comme il se doit. Votre lien avec TableC est à travers TableB donc le lien ne sera pas connecté si aucun enregistrement TableB.

Modification INNER JOIN à LEFT OUTER ainsi - bien que ce soit vraiment un interne autant que les données concernées.

1

Si vous exécutez une requête sans INNER JOIN, tous les enregistrements seront nullBD, n'est-ce pas? Ainsi, INNER JOIN ne trouve aucun enregistrement correspondant, c'est pourquoi il n'y a pas de résultat.

0

Voici le code en tant qu'exemple d'utilisation d'une jointure à gauche pour les tables b et c.

declare @TableA table (Adata1 char(2), Adata2 char(2)) 
declare @TableB table (Bdata1 char(2), Bdata2 char(2)) 
declare @TableC table (Cdata1 char(2), Cdata2 char(2)) 

;Insert @TableA 
Select 'A', 'A' union all 
Select 'B', 'B' union all 
Select 'C', 'C' 

;Insert @TableB 
Select 'Ab', 'Ab' union all 
Select 'B', 'B' union all 
Select 'C', 'C' 

;Insert @TableC 
Select 'A', 'A' union all 
Select 'B', 'B' union all 
Select 'Cb', 'Cb' 

--Select * From @TableA 
--Select * From @TableB 
--Select * From @TableC 

Select * from @TableA 
LEFT OUTER JOIN @TableB on Adata1 = Bdata1 
LEFT OUTER JOIN @TableC on Bdata1 = Cdata1 

Les résultats sont:

Adata1 Adata2 Bdata1 Bdata2 Cdata1 Cdata2 
A   A NULL NULL NULL NULL 
B   B B B B B 
C   C C Cb NULL NULL 
Questions connexes