Consulta SQL, contagem com contagem 0
Pergunta
Eu tenho três tabelas:página, anexo, anexo de página
Eu tenho dados como este:
page
ID NAME
1 first page
2 second page
3 third page
4 fourth page
attachment
ID NAME
1 foo.word
2 test.xsl
3 mm.ppt
page-attachment
ID PAGE-ID ATTACHMENT-ID
1 2 1
2 2 2
3 3 3
Gostaria de obter o número de anexos por página também quando esse número é 0.Eu tentei com:
select page.name, count(page-attachment.id) as attachmentsnumber
from page
inner join page-attachment on page.id=page-id
group by page.id
Estou recebendo esta saída:
NAME ATTACHMENTSNUMBER
second page 2
third page 1
Eu gostaria de obter esta saída:
NAME ATTACHMENTSNUMBER
first page 0
second page 2
third page 1
fourth page 0
Como faço para obter a parte 0?
Solução
Altere sua "junção interna" para "junção externa esquerda", que significa "obtenha todas as linhas à esquerda da junção, mesmo que não haja uma linha correspondente à direita".
select page.name, count(page-attachment.id) as attachmentsnumber
from page
left outer join page-attachment on page.id=page-id
group by page.name
Outras dicas
Aqui está outra solução usando subconsulta.
SELECT
p.name,
(
SELECT COUNT(*) FROM [page-attachment] pa
WHERE pa.[PAGE-ID] = p.id
) as attachmentsnumber
FROM page p
Dependendo do banco de dados, para velocidade, você pode usar o comando UNION.
O SQL é mais longo, mas, dependendo do banco de dados, agiliza separando "contar coisas que estão lá" e "contar coisas que não estão lá".
(
select page.name, count(page-attachment.id) as attachmentsnumber
from page
inner join page-attachment on page.id=page-id
group by page.id
)
UNION
(
select page.name, 0 as attachmentsnumber
from page
where page.id not in (
select page-id from page-attachment)
)
O banco de dados para o qual preciso desta solução tem 20 páginas em mais de um milhão de anexos.O UNION fez com que ele fosse executado em 13 segundos, em vez de tanto tempo que fiquei entediado e tentei de outra maneira (algo acima de 60 segundos antes de eliminar os métodos de junção externa e subconsulta).
Você deseja uma junção à esquerda, em vez de uma junção interna, pois isso permite que os registros não existam.
A junção ESQUERDA é sua amiga.Para saber mais sobre os diferentes tipos de junção, consulte http://en.wikipedia.org/wiki/Join_(SQL)
Usa isto:
SELECT p.name,(
SELECT COUNT(*) FROM [page-attachment] pa WHERE pa.[PAGE-ID] = p.id) as attachmentsnumber
FROM page p