2010-02-09 9 views
2

J'ai trois tables (pour l'argument) individuelles, email et attribut. individual_Ref la clé étrangère qui lie l'individu à l'email et à l'attribut.Je ne comprends pas pourquoi ces deux requêtes donnent des résultats différents

Il n'est pas nécessaire qu'un individu donné soit représenté sur la table attributaire car il se peut qu'il n'ait jamais ajouté d'attribut et qu'il puisse apparaître plusieurs fois s'il possède plusieurs attributs.

Je veux obtenir une liste de références individuelles et le nombre d'un attribut particulier pour eux. Mais il faut effectuer une recherche par adresse e-mail car il est permis aux personnes de partager des adresses e-mail (ne me lancez pas) ...

Mon premier coup de couteau a été

select e.individual_ref, count(a.attr_Code_ref) 
from email e left join attribute a on e.individual_Ref = a.individual_ref 
where e.email_Address = '[email protected]' 
and a.attr_code_Ref = 4119 
group by e.individual_ref 

à l'aide d'une jointure gauche pour assurer I obtenir un ref individuel de l'email s'il en existe un et s'assurer que j'obtiens un résultat s'il y a un ref individuel dans l'email mais pas dans l'attribut. Ou alors je pensais que puisque ce ne retourne aucune ligne, mais ...

select e.individual_ref, 
(select count(a.attr_Code_ref) from attribute a where a.attr_code_Ref = 4119 and a.individual_ref = e.individual_ref) 
from email e 
where e.email_Address = '[email protected]' 
group by e.individual_REf 

renvoie une ligne avec un individual_Ref et un nombre de 0

Je ne suggère pas SQL est cassé plus que je crois comprendre .. alors je suppose que "quelle est ma confusion?" est la question.

+0

+1 pour obtenir les gens à considérer l'effet de une clause WHERE en contexte avec le JOIN –

+0

merci pour toutes les réponses! –

Répondre

1

Lors de la conversion d'un sous-requête à un LEFT JOIN, les conditions dans WHERE en corrélation du sous-requête vont à la clause ON de la jointure, à la clause WHERE:

SELECT e.individual_ref, count(a.attr_Code_ref) 
FROM email e 
LEFT JOIN 
     attribute a 
ON  a.individual_ref = e.individual_Ref 
     AND a.attr_code_Ref = 4119 
WHERE e.email_Address = '[email protected]' 
GROUP BY 
     e.individual_ref 
+0

Je suppose qu'il est évident que je suis autodidacte et que un peu de connaissance est une chose dangereuse :-) Merci pour votre réponse - les choses sont un peu plus claires maintenant ... –

3

la partie suivante provoque la jonction à modifier:

from email e left join attribute a on e.individual_Ref = a.individual_ref 
where e.email_Address = '[email protected]' 
and a.attr_code_Ref = 4119 

En plaçant une clause where sur la a.attr_code vous avez tourné la jointure gauche dans une jointure interne par exemple où aucun enregistrement d'attribut n'existe, il renvoie null, ce qui échoue à la clause where. (Puisque a.attr_code_ref ne peut être 4119, il n'y avait pas d'enregistrement.)

vous devez permettre a.attr_code_ref = 4199 or a.attr_code_ref is null

+0

Shorter: isnull (a.attr_code_ref, 0) = 4199 – momobo

+0

Vraiment plus court, mais je me demande (havnt vérifié) si cela le fait garder SARGable ou non. La fonction appliquée au champ testé tend à le casser. – Andrew

+1

'= null' n'est jamais vrai; essayez 'est nul' – Andomar

1

Modifier le premier dans:

select e.individual_ref, count(a.attr_Code_ref) 
from email e left join attribute a on e.individual_Ref = a.individual_ref 
where e.email_Address = '[email protected]' 
and (a.attr_code_Ref = 4119 or a.individual_ref is null) 
group by e.individual_ref 

et vous obtenez les mêmes résultats

0

Dans la première requête, vous joignez les deux tables et recherchez les lignes qui correspondent à vos deux conditions - il n'y en a aucune. Dans la deuxième requête, vous obtenez les lignes de la première table correspondant à la condition de l'e-mail (il y en a une) et le nombre de lignes correspondant à votre deuxième condition de l'autre table, il y a 0 de ceux.