2010-07-12 8 views
0

Est-il possible de faire un CROSS JOIN entre 2 tables, suivi d'un LEFT JOIN sur une 3ème table, suivi éventuellement d'autres jointures à gauche? J'utilise SQL Server 2000/2005.Cross Join suivi de Left Join

Je cours la requête suivante, qui est assez droite IMO, mais j'obtiens une erreur.

select P.PeriodID, 
     P.PeriodQuarter, 
     P.PeriodYear, 
     M.Name, 
     M.AuditTypeId, 
     A.AuditId 
from Period P, Member M 

LEFT JOIN Audits A 
ON P.PeriodId = A.PeriodId 

WHERE 
    P.PeriodID > 29 AND P.PeriodID < 38 
    AND M.AuditTypeId in (1,2,3,4) 
order by M.Name 

Je reçois l'erreur suivante:

Msg 4104, Level 16, State 1, Line 1 The multi-part identifier "P.PeriodId" could not be bound.

Si je retire la LEFT JOIN, la requête fonctionne. Cependant, j'ai besoin de LEFT JOIN, car il y a plus d'informations que je dois tirer des autres tables.

Qu'est-ce que je fais mal? Y a-t-il un meilleur moyen d'y arriver?

Répondre

1

Vous ne pouvez pas combiner implicite et explicite joint - see this running example. CROSS JOINs devrait être si rarement utilisé dans un système, que je voudrais que chacun soit explicite pour s'assurer qu'il ne s'agit clairement pas d'une erreur de codage ou d'une erreur de conception.

Si vous voulez faire une jointure externe gauche implicite, faire (pas pris en charge sur SQL Azure):

select P.PeriodID, 
     P.PeriodQuarter, 
     P.PeriodYear, 
     M.Name, 
     M.AuditTypeId, 
     A.AuditId 
from #Period P, #Member M, #Audits A 
WHERE 
    P.PeriodID > 29 AND P.PeriodID < 38 
    AND M.AuditTypeId in (1,2,3,4) 
    AND P.PeriodId *= A.PeriodId 
order by M.Name​ 
+0

Thnx. Cela rend les choses plus claires pour moi maintenant. Faire une jointure croisée est la seule façon que je peux penser pour résoudre mon problème particulier. Que fait l'opérateur '* ='? –

+0

@Saajid Imsail * = est l'ancien opérateur LEFT JOIN pour les jointures implicites. –

+0

Cet opérateur est peu fiable et obsolète, le correctif approprié consiste à utiliser des jointures explicites. Il n'y a aucune excuse pour ne pas utiliser de jointures explicites dans une requête. – HLGEM

5

vous oublié CROSS JOIN dans votre requête:

select P.PeriodID, 
     P.PeriodQuarter, 
     P.PeriodYear, 
     M.Name, 
     M.AuditTypeId, 
     A.AuditId 
from Period P CROSS JOIN Member M 

LEFT JOIN Audits A 
ON P.PeriodId = A.PeriodId 

WHERE 
    P.PeriodID > 29 AND P.PeriodID < 38 
    AND M.AuditTypeId in (1,2,3,4) 
order by M.Name 
+0

Je ne ai pas besoin de le préciser, autant que je sache. La requête fonctionne correctement si je supprime le LEFT JOIN sur la table Audits. D'après ce que j'ai lu, mon OP définit une jointure croisée implicite. –

+0

OK donc j'ai essayé votre code, et ça marche maintenant .. Mais pourquoi? Cela n'a pas de sens. –

+0

@Sajajid: SQL A tendance à regarder des clauses entières à la fois. Par exemple vous ne pouvez pas dire 'select a + b comme c, 2 * c comme double_c' Parce que le' c' n'est pas défini quand la clause select commence. La même chose se produit lors du mélange de jointures de style ancien et nouveau. Les pièces entre les virgules dans la clause from sont examinées, comme si elles étaient en parallèle. Donc, le P défini sur le côté gauche de la virgule n'est pas vu sur la droite. Voir http://stackoverflow.com/questions/1080097/the-multi-part-identifier-could-not-be-bound-on-sql-server-2005-8/1080407#1080407 pour un autre exemple. –