Mysql
 sql >> Base de données >  >> RDS >> Mysql

LEFT JOIN ne renvoie pas tous les enregistrements de la table de gauche

Le problème pourrait être que vous filtrez sur la table jointe en utilisant la condition where qui filtrera également les services du département qui n'ont pas de correspondance dans la jointure, déplacez le filtrage dans la jointure et ne laissez que les filtres sur d dans la clause where :

SELECT d.mt_code,
   d.dep_name,
   d.service_name,
   COUNT(t.id)
FROM DepartmentService AS d
LEFT JOIN tbl_outgoing AS t 
  ON d.mt_code = t.depCode 
    AND t.smsc = "mobitelMT"
    AND t.sendDate BETWEEN '2014-07-01' AND '2014-07-02'
WHERE d.service_type = 'MT'
GROUP BY d.mt_code

Pour expliquer pourquoi cela se produit, je vais vous expliquer ce qui se passe avec votre requête et avec ma requête, en tant qu'ensemble de données, j'utiliserai ceci :

states
 ____ _________ 
| id | state   |
|  1 | Germany |
|  2 | Italy   |
|  3 | Sweden  |
|____|_________|

cities

 ____ ________ ___________ ____________
| id | city   | state_fk  | population |
|  1 | Berlin |        1  |         10 |
|  2 | Milan  |        2  |          5 |
|____|________|___________|____________|

Je vais d'abord passer en revue votre requête.

SELECT s.id, s.state, c.population, c.city
FROM states s
LEFT JOIN cities c
ON c.state_fk = s.id
WHERE c.population < 10

Alors allons-y pas à pas, vous sélectionnez les trois états, rejoignez à gauche les villes se terminant par :

 ____ _________ ____________ ________
| id | state   | population | city   |
|  1 | Germany |         10 | Berlin |
|  2 | Italy   |          5 | Milan  |
|  3 | Sweden  |       NULL | NULL   |
|____|_________|____________|________|

Ensuite, vous filtrez la population en utilisant WHERE c.population < 10 , à ce stade votre gauche avec ceci :

 ____ _________ ____________ ________
| id | state   | population | city   |
|  2 | Italy   |          5 | Milan  |
|____|_________|____________|________|

Vous perdez l'Allemagne parce que la population de Berlin était de 10 mais vous avez également perdu la Suède qui avait NULL, si vous vouliez garder les nuls vous auriez dû le spécifier dans la requête :

WHERE (c.population < 10 OR IS NULL c.population)

Qui renvoie :

 ____ _________ ____________ ________
| id | state   | population | city   |
|  2 | Italy   |          5 | Milan  |
|  3 | Sweden  |       NULL | NULL   |
|____|_________|____________|________|

Maintenant ma requête :

SELECT s.id, s.state, c.population, c.city
FROM states s
LEFT JOIN cities c
ON c.state_fk = s.id
  AND c.population < 10

Avant de joindre les deux, on filtre les villes du tableau (en utilisant le AND c.population < 10 condition après le ON ), il reste :

 ____ ________ ___________ ____________
| id | city   | state_fk  | population |
|  2 | Milan  |        2  |          5 |
|____|________|___________|____________|

Parce que Milan est la seule ville avec moins de 10 habitants, maintenant on peut joindre les deux tables :

 ____ _________ ____________ ________
| id | state   | population | city   |
|  1 | Germany |       NULL | NULL   |
|  2 | Italy   |          5 | Milan  |
|  3 | Sweden  |       NULL | NULL   |
|____|_________|____________|________|

Comme vous pouvez le voir, les données du tableau de gauche restent car la condition de filtrage a été appliquée uniquement au tableau des villes.

Le jeu de résultats change en fonction de ce que vous voulez réaliser, si par exemple vous voulez filtrer l'Allemagne parce que Berlin a une population inférieure à 10 et garder la Suède, vous devez utiliser la première approche en ajoutant le IS NULL condition, si vous souhaitez la conserver à la place, vous devez utiliser la deuxième approche et préfiltrer la table à droite de la jointure gauche.