SQL left join排除不匹配的记录
SQL left join exclude non matching records
我正在处理此查询(运行 在 MySQL 5.6 上):
SELECT
veicoli_contratti.targa AS targa,
veicoli_contratti.canone_noleggio AS canone,
anag_convenzionati.nome AS convenzionato,
SUM(noleggio_veicoli.fatt_prezzo_totale_noleggio) AS noleggi_incasso,
noleggio_veicoli.modalita_noleggio,
COUNT(DISTINCT noleggio_veicoli.id) AS noleggi
FROM
veicoli_contratti
LEFT JOIN
noleggio_veicoli ON veicoli_contratti.id = noleggio_veicoli.id_veicolo
INNER JOIN
anag_convenzionati ON veicoli_contratti.id_convenzionato = anag_convenzionati.id
WHERE
(veicoli_contratti.data_cancellazione IS NULL)
AND (veicoli_contratti.targa <> '')
AND (noleggio_veicoli.data_cancellazione IS NULL)
AND (anag_convenzionati.data_cancellazione IS NULL)
AND (YEAR(noleggio_veicoli.rientro_data) = 2020)
AND (MONTH(noleggio_veicoli.rientro_data) = 10)
AND ((noleggio_veicoli.stato_noleggio = 'C')
OR (noleggio_veicoli.stato_noleggio = 'F')
)
AND ((noleggio_veicoli.modalita_noleggio = 'S')
OR (noleggio_veicoli.modalita_noleggio = 'OPO')
OR (noleggio_veicoli.modalita_noleggio = 'M')
)
AND (veicoli_contratti.stato = 'OPERATIVA')
GROUP BY anag_convenzionati.id , veicoli_contratti.id , noleggio_veicoli.modalita_noleggio
ORDER BY convenzionato , noleggi DESC , canone DESC , noleggi_incasso DESC ;
我认为即使 table noleggio_veicoli
中没有匹配的记录,LEFT JOIN
子句也会生成一条记录,但这并没有发生。
结果仅包括在 veicoli_contratti
和 noleggio_veicoli
之间找到匹配项的记录。
我也尝试在 WHERE
子句中添加 OR noleggio_veicoli.id IS NULL
但这不是解决方案。
我怎样才能解决这个问题?
我创建了一个 SQL fiddle 来尝试这个 here
你的理解是正确的。但是,where
子句正在“撤消”LEFT JOIN
。为什么?
您有这样的条件:
AND ((noleggio_veicoli.stato_noleggio = 'C') OR (noleggio_veicoli.stato_noleggio = 'F'))
好吧,NULL
不符合这些条件,所以不匹配项被过滤掉了。此条件(连同其他条件)应包含在 ON
子句中。对于这个,它看起来像:
AND noleggio_veicoli.stato_noleggio IN ('C', 'F')
我正在处理此查询(运行 在 MySQL 5.6 上):
SELECT
veicoli_contratti.targa AS targa,
veicoli_contratti.canone_noleggio AS canone,
anag_convenzionati.nome AS convenzionato,
SUM(noleggio_veicoli.fatt_prezzo_totale_noleggio) AS noleggi_incasso,
noleggio_veicoli.modalita_noleggio,
COUNT(DISTINCT noleggio_veicoli.id) AS noleggi
FROM
veicoli_contratti
LEFT JOIN
noleggio_veicoli ON veicoli_contratti.id = noleggio_veicoli.id_veicolo
INNER JOIN
anag_convenzionati ON veicoli_contratti.id_convenzionato = anag_convenzionati.id
WHERE
(veicoli_contratti.data_cancellazione IS NULL)
AND (veicoli_contratti.targa <> '')
AND (noleggio_veicoli.data_cancellazione IS NULL)
AND (anag_convenzionati.data_cancellazione IS NULL)
AND (YEAR(noleggio_veicoli.rientro_data) = 2020)
AND (MONTH(noleggio_veicoli.rientro_data) = 10)
AND ((noleggio_veicoli.stato_noleggio = 'C')
OR (noleggio_veicoli.stato_noleggio = 'F')
)
AND ((noleggio_veicoli.modalita_noleggio = 'S')
OR (noleggio_veicoli.modalita_noleggio = 'OPO')
OR (noleggio_veicoli.modalita_noleggio = 'M')
)
AND (veicoli_contratti.stato = 'OPERATIVA')
GROUP BY anag_convenzionati.id , veicoli_contratti.id , noleggio_veicoli.modalita_noleggio
ORDER BY convenzionato , noleggi DESC , canone DESC , noleggi_incasso DESC ;
我认为即使 table noleggio_veicoli
中没有匹配的记录,LEFT JOIN
子句也会生成一条记录,但这并没有发生。
结果仅包括在 veicoli_contratti
和 noleggio_veicoli
之间找到匹配项的记录。
我也尝试在 WHERE
子句中添加 OR noleggio_veicoli.id IS NULL
但这不是解决方案。
我怎样才能解决这个问题?
我创建了一个 SQL fiddle 来尝试这个 here
你的理解是正确的。但是,where
子句正在“撤消”LEFT JOIN
。为什么?
您有这样的条件:
AND ((noleggio_veicoli.stato_noleggio = 'C') OR (noleggio_veicoli.stato_noleggio = 'F'))
好吧,NULL
不符合这些条件,所以不匹配项被过滤掉了。此条件(连同其他条件)应包含在 ON
子句中。对于这个,它看起来像:
AND noleggio_veicoli.stato_noleggio IN ('C', 'F')