Estou desenvolvendo uma aplicação estatística para analisar respostas de um questionário socieconômico de alunos ingressantes de uma universidade. Preciso fazer consultas do tipo “Quantidade de mulheres entre 17 e 20 anos” (só um exemplo). Estou utilizando o comando COUNT nos SQLs e está tudo funcionando, porém encontrei um pequeno problema: quando não há nenhuma mulher entre 17 e 20 anos, o resultado da consulta não retorna linha nenhuma e eu precisava que retornasse o valor 0. Tentei usar COALESCE(nome_do_campo, 0), porém não funciona. Já pesquisei bastante na net. Alguém poderia me ajudar a resolver isso ou realmente não tem solução via SQL?
Que BD usas? Em todos os que trabalhei sempre tenho ideia de devolver 0 quando não há registos.
drsmachado
Um case não resolve o problema?
Um if?
Decode?
Mariana_
Estou usando MySQL e um CASE também não funcionou… já utilzei Firebird e SQL Server e me lembro que isso funcionava nesses BDs. O estranho dessa situação é que nem um NULL é exibido, ou seja, não mostra linha nenhuma no resultado quando não há dados.
No Oracle, ao executar a seguinte query, que retornará 0 linhas…
… a saída é o número 0. Não sei bem como deve funcionar isso no MySQL, mas deveria ter o mesmo comportamento, visto que essa é uma cláusula comum a todos os bancos que adotam o padrão ANSI SQL. Não ocorre nenhum erro durante a execução de seu código?
Mariana_
Esse comando eu não conheço, vou dar uma pesquisada e tentar usar
Mariana_
FabricioPJ:
No Oracle, ao executar a seguinte query, que retornará 0 linhas…
… a saída é o número 0. Não sei bem como deve funcionar isso no MySQL, mas deveria ter o mesmo comportamento, visto que essa é uma cláusula comum a todos os bancos que adotam o padrão ANSI SQL. Não ocorre nenhum erro durante a execução de seu código?
Então, no Firebird e SQL Server só assim também sairia 0 D:
Não dá nenhum erro, não. Os valores aparecem corretamente para a query que eu postei nos comentários de cima ai, porém a linha que não tem dados não é exibida ao invés de mostrar 0
Rodrigo_Sasaki
A sintaxe de utilização dela é igual a do COALESCE, só que é específica do MySQL, se não me engano// Com IFNULL
SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0)) FROM Products
// Com COALESCE
SELECT ProductName,UnitPrice*(UnitsInStock+COALESCE(UnitsOnOrder,0)) FROM Productshttp://www.w3schools.com/sql/sql_isnull.asp
Acho que o seu problema é que você está gerando os totais a partir dos resultados e não a partir de uma lista de referência.
Imagine por exemplo que quero contar o percentual de torcedores de 5 times, e a tabela tenha os seguintes registros:
ID NOME TIME
1 ABEL PALMEIRAS
2 BRUNO CORINTHIANS
3 CARLOS SÃO PAULO
4 DANIEL SANTOS
E espera o seguinte resultado:
TIME QUANTIDADE
PALMEIRAS 1
CORINTHIANS 1
SÃO PAULO 1
SANTOS 1
JUVENTUS 0
Baseado na primeira tabela apenas você nunca conseguirá o resultado abaixo, pois ele nem sabe da existência do Juventus pra começar.
O que você precisaria nesse caso é fazer uma LEFT JOIN da tabela de Times com a tabela de Torcedores.
No seu caso, você precisa criar registros de referência para fazer LEFT JOIN com as respostas dadas.
Mariana_
digaoneves:
A sintaxe de utilização dela é igual a do COALESCE, só que é específica do MySQL, se não me engano// Com IFNULL
SELECT ProductName,UnitPrice*(UnitsInStock+IFNULL(UnitsOnOrder,0)) FROM Products
// Com COALESCE
SELECT ProductName,UnitPrice*(UnitsInStock+COALESCE(UnitsOnOrder,0)) FROM Productshttp://www.w3schools.com/sql/sql_isnull.asp
SELECT A.DESCRICAO,
IF COUNT(AL.ID) IS NOT NULL THEN COUNT(AL.ID) ELSE 0 END AS TOTAL
FROM ALUNOS AL
INNER JOIN RESPOSTAS R ON R.ALUNO = AL.ID AND R.PERGUNTA = 5
INNER JOIN ALTERNATIVAS A ON R.ALTERNATIVA = A.ID
WHERE AL.ANO = 2012
GROUP BY A.LETRA
ORDER BY A.LETRA
O primeiro rodou, porém ainda não funcionou D:
O segundo está dando erro de sintaxe
drsmachado
Veja a dica do abelbueno. Inner joins só consideram os valores que existem nas duas tabelas. Caso queira valores, independente de existirem em A ou B, precisa do left join.
Mariana_
AbelBueno, entendi o que você quis dizer, porém eu tenho uma tabela ALTERNATIVAS que contém as opções “16 anos”, “17 anos”, “18 anos”, etc. Só que nenhum registro da tabela ALUNOS está vinculado à alternativa “16 anos”. Nesse caso ele saberia da existência do “16 anos”, certo? Seria o caso de mudar pra LEFT JOIN então?
Rodrigo_Sasaki
É, isso ta bem estranho, a gente até poderia sugerir outras opções de como verificar se o resultado está vindo Null, como:SELECT A.DESCRICAO,
CASE WHEN ISNULL(COUNT(AL.ID)) THEN 0 ELSE COUNT(AL.ID) END AS TOTAL
FROM ALUNOS AL
INNER JOIN RESPOSTAS R ON R.ALUNO = AL.ID AND R.PERGUNTA = 5
INNER JOIN ALTERNATIVAS A ON R.ALTERNATIVA = A.ID
WHERE AL.ANO = 2012
GROUP BY A.LETRA
ORDER BY A.LETRA Porém aparentemente o problema é que não está retornando nada (o que eu nunca vi acontecer), porque se estivesse vindo nulo, o COALESCE ja resolveria.
Mariana_
Sim!!
Mudei a junção das tabelas para LEFT e deu na mesma, não sei o que fazer mais e é realmente importante que esses zeros apareçam =/
drsmachado
Então, como diria o Jack, vamos por partes. Posta as duas tabelas para vermos.
Rodrigo_Sasaki
Independente de INNER ou LEFT, o seu problema na verdade não é esse (pode ser que seja um outro problema, mas não o em questão), de qualquer maneira, se nada fosse encontrado, deveria retornar um 0.
Vi esse post procurando no google, não sei o que tem dentro porque não tenho acesso, mas pelo nome parece que pode te ajudar.
A
AbelBueno
Três observações:
O LEFT JOIN dá prioridade a tabela do lado esquerdo no select. Existe também o RIGHT JOIN, para dar prioridade ao lado direito.
Se manter um INNER JOIN no meio da query, pode anular o efeito do LEFT/RIGHT join anterior.
Se colocar no WHERE alguma condição que dependa do lado sem prioridade, você também vai anular o efeito do LEFT/RIGHT join.
17 anos -> 6
18 anos -> 8
18 anos -> 14
19 anos -> 3
19 anos -> 4
20 anos -> 2
20 anos -> 5
21 anos -> 3
21 anos -> 4
22 a 24 anos -> 2
22 a 24 anos -> 1
25 a 29 anos -> 4
25 a 29 anos -> 8
30 anos ou mais -> 2
30 anos ou mais -> 6
Resultado ESPERADO (pois a pergunta 2 tem oito alternativas e a pergunta 1 tem duas):
[color=red]17 anos -> 0[/color]
17 anos -> 6
18 anos -> 8
18 anos -> 14
19 anos -> 3
19 anos -> 4
20 anos -> 2
20 anos -> 5
21 anos -> 3
21 anos -> 4
22 a 24 anos -> 2
22 a 24 anos -> 1
25 a 29 anos -> 4
25 a 29 anos -> 8
30 anos ou mais -> 2
30 anos ou mais -> 6
Mariana_
Vou fazer uns testes aqui então com RIGHT, etc (acredito que o conteúdo da cláusula WHERE não dará problema)