Mysql
 sql >> Database >  >> RDS >> Mysql

LEFT JOIN non restituisce tutti i record dalla tabella di sinistra

Il problema potrebbe essere che stai filtrando sulla tabella unita usando la condizione where che filtrerà anche i servizi del dipartimento che non hanno una corrispondenza nel join, sposta il filtro nel join e lascia solo i filtri su d nella clausola 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

Per spiegare perché questo accade ti guiderò attraverso cosa succede con la tua query e con la mia query, come set di dati userò questo:

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

cities

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

Per prima cosa esaminerò la tua domanda.

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

Quindi andiamo passo dopo passo, selezioni i tre stati, a sinistra unisciti alle città che finiscono con:

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

Filtra la popolazione usando WHERE c.population < 10 , a questo punto sei a sinistra con questo:

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

Hai perso la Germania perché la popolazione di Berlino era di 10 persone ma ​​hai perso anche la Svezia che aveva NULL, se volevi mantenere i null avresti dovuto specificarlo nella query:

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

Che restituisce:

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

Ora la mia domanda:

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

Prima di unire le due, filtriamo le città della tabella (usando il AND c.population < 10 condizione dopo ON ), ciò che resta è:

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

Perché Milano è l'unica città con meno di 10 abitanti, ora possiamo unire i due tavoli:

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

Come puoi vedere, i dati della tabella di sinistra rimangono perché la condizione di filtro è stata applicata solo alla tabella delle città.

Il set di risultati cambia a seconda di ciò che vuoi ottenere, se ad esempio vuoi filtrare la Germania perché Berlino ha una popolazione minore di 10 e mantenere la Svezia dovresti usare il primo approccio aggiungendo il IS NULL condizione, se invece vuoi mantenerla, dovresti utilizzare il secondo approccio e prefiltrare la tabella a destra del join sinistro.