2014-05-20 3 views
0

j'ai deux requêtes pour compter les données:Deux requêtes de sélection avec un nombre à une requête

SELECT x.Id, COUNT(DISTINCT y.Id) 
FROM X x 
INNER JOIN Y y ON x.Id = y.otherId 


SELECT x.Id, COUNT(DISTINCT z.Id) 
FROM X x 
INNER JOIN Z z ON x.Id = z.otherId 

Les deux requêtes renvoient la juste valeur lors de l'exécution séparée.

Mais je voudrais combiner ces requêtes à une seule requête:

SELECT x.Id, COUNT(DISTINCT y.Id), COUNT(DISTINCT z.Id) 
FROM X x 
INNER JOIN Y y ON x.Id = y.otherId 
INNER JOIN Z z ON x.Id = z.otherId 

Quand je fais cela, les deux chefs d'accusation sont faux par rapport aux requêtes exécutées séparément. Pourquoi est-ce que cela se produit, je suis vraiment confus. La solution pourrait être simple, mais je n'ai vraiment aucune idée pour le moment.

Répondre

6

Le inner join filtre les valeurs qui ne correspondent pas dans les deux tables. Pour faire ce que vous voulez, utilisez left outer join:

SELECT x.Id, COUNT(DISTINCT y.Id), COUNT(DISTINCT z.Id) 
FROM X x 
LEFT JOIN Y y ON x.Id = y.otherId 
LEFT JOIN Z z ON x.Id = z.otherId ; 

Je mets en garde contre cette approche, car elle produit un résultat intermédiaire qui est le produit cartésien du nombre de valeurs correspondant dans les deux tableaux (pour une valeur donnée de x.ID) . Au lieu de cela, vous pouvez utiliser des sous-requêtes. Voici un exemple utilisant des sous-requêtes imbriquées

select x.id, 
     (select count(distinct y.id) from y where x.id = y.otherId), 
     (select count(distinct z.id) from z where x.id = z.otherid) 
from x; 
+0

Bonjour, pourquoi la jointure interne filtre-t-elle les valeurs qui ne correspondent pas dans les deux tables? Par exemple j'utilise x.Id = y.otherId, cela devrait obtenir les valeurs correspondantes, n'est-ce pas? – Swag

+1

@ y451n. . . Certains 'x.id' ont des correspondances dans la table' y'; certains ont des correspondances dans la table 'z'. Certains dans les deux, mais certains seulement dans un. Avec la jointure interne, vous obtenez uniquement les correspondances dans les deux tables. –

0

INNER JOIN est comme une intersection. La première requête compte tous les y.id distincts qui ont y.otherId dans la table , mais pas nécessairement dans z. La seconde est tous distincts z.idz.otherId est en x, mais pas nécessairement en y. La troisième requête combinée sera y.id telle que y.otherId est dans x ET dans z.otherId, et vice versa.

Si vous voulez les deux comptes, vous pouvez toujours les assembler avec UNION, bien que vos deux réponses soient placées dans des rangées différentes, par opposition à des colonnes différentes.

Questions connexes