MySQL « Проблема с count() и Left Join в MySQL

Почему count в sql-запросе с left outer join не возвращает 0, если не находит строки подходящие под условие?
Из мануала MySQL
// COUNT() returns 0 if there were no matching rows

/** * GeSHi (C) 2004 - 2007 Nigel McNie, 2007 - 2008 Benny Baumann * (http://qbnz.com/highlighter/ and http://geshi.org/) */ .sql.geshi_code {font-family:monospace;} .sql.geshi_code .imp {font-weight: bold; color: red;} .sql.geshi_code .kw1 {color: #993333; font-weight: bold;} .sql.geshi_code .co1 {color: #808080; font-style: italic;} .sql.geshi_code .co2 {color: #808080; font-style: italic;} .sql.geshi_code .coMULTI {color: #808080; font-style: italic;} .sql.geshi_code .es0 {color: #000099; font-weight: bold;} .sql.geshi_code .br0 {color: #66cc66;} .sql.geshi_code .sy0 {color: #66cc66;} .sql.geshi_code .st0 {color: #ff0000;} .sql.geshi_code .nu0 {color: #cc66cc;} .sql.geshi_code span.xtra { display:block; }

SELECT t.`id`, t.`name`, COUNT(t2.`id`) AS `cat_count`
FROM `ch_razdel2` AS t
LEFT JOIN `ch_razdel2_info` AS t2 ON t.`id` = t2.`id_cat`
WHERE <>
GROUP BY t.`id`
ORDER BY t.`name`
 


Таблица t (разделы)
id | name

Таблица t2 (позиции, относящиеся к разделам)
id | id_cat | text | result | time1 | time2

Т.е. этим запросом я могу получить только список разделов с количеством позиций, если они не пустые.

1 ответов


Для оптимизации можно попробовать сначала наложить фильтры на большую таблицу, и только после этого соединять ее.


SELECT t.`id`, t.`name`, COUNT(t2.`id`) AS `cat_count`
FROM `ch_razdel2` AS t

LEFT JOIN (
    select `id`, `id_cat`
    from `ch_razdel2_info`
    where `result` = 0 AND `time1` < {current_time} AND `time2` > {current_time}
  ) AS t2
  ON t.`id` = t2.`id_cat`

GROUP BY t.`id`
ORDER BY t.`name`
 


WHERE t2.`result` = 0 AND t2.`time1` < {current_time}
AND t2.`time2` > {current_time}
 
"превращают" (не совсем корректный термин) LEFT JOIN в INNER - если в t2 нет записей соответсвующих условию в ON, все поля у t2 - NULL, записи будут выкинуты в WHERE . Если я правильно понял вопрос, то надо просто перенести условия, касающиеся t2 из WHERE в ON:


SELECT t.`id`, t.`name`, COUNT(t2.`id`) AS `cat_count`
FROM `ch_razdel2` AS t

LEFT JOIN `ch_razdel2_info` AS t2 (ON t.`id` = t2.`id_cat` AND
t2.`result` = 0 AND t2.`time1` < {current_time}
AND t2.`time2` > {current_time} )

GROUP BY t.`id`
ORDER BY t.`name`