É melhor sempre especificar o tipo de junção que você está fazendo. Por padrão, ele está usando uma junção interna. Uma junção interna mostrará apenas itens que possuem uma correspondência em ambas as tabelas. No seu exemplo, você deseja que todos os registros retornados de placemark_types e zero-para-muitos dos registros da tabela de marcadores correspondam.
Para isso, basta usar uma junção à esquerda, como mostrado abaixo. A junção à esquerda sempre retorna todos os registros do lado esquerdo (placemark_types) e somente os registros correspondentes do lado direito (marcadores). Em seguida, vamos nos livrar do COUNT(*)
e usar COUNT (placemarks.type_id), porque não queremos contar todas as linhas, apenas aquelas com correspondências na tabela de marcadores. Senão você ganharia 1 mesmo quando o seu zero correspondesse porque ainda estaria contando os placemark_types.
SELECT COUNT(placemarks.type_id) AS type_count, placemark_types.name
FROM placemark_types
LEFT JOIN placemarks ON placemark_types.id = placemarks.type_id
WHERE placemark_types.parent_id = 0
GROUP BY placemark_types.id
Para entender melhor, execute a consulta sem o GROUP BY
. Você verá que mesmo quando não houver entradas na tabela de marcadores, você receberá os campos da tabela placemark_types e os valores nulos dos campos de marcadores. Como o COUNT(placemarks.type_id)
não contará nulos, isso fornecerá o número correto.