Oi gente, tudo bem,
to apanhando um pouco do sql aki, porém preciso fazer o seguinte relatório,
preciso fazer um relatorio que traga o nome das pessoas e suas respectivas idades, eu fiz o seguinte abaixo e funcionou:
SELECT
pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5)) AS idade
FROM
pessoas
Porém agora preciso fazer um relatório que divida as pessoas entre grupos de idade.
Exemplo
Grupo de idade - Quantidade de pessoas
<=20 - 4
25-30 - 8
31-30 - 2
36-30 - 5
.
.
.
86-90 - 2
91
Porém não faço ideia de como faze-lo, alguém poderia dar um help
ps: uso mysql
Wikipedia: Procedimento armazenado ou Stored Procedure é uma coleção de comandos em SQL para dispensamento de Banco de dados. Encapsula tarefas repetitivas, aceita parâmetros de entrada e retorna um valor de status (para indicar aceitação ou falha na execução). O procedimento armazenado pode reduzir o tráfego na rede, melhorar a performance, criar mecanismos de segurança, etc.
Uma stored procedure é como um programa, escrito para ser pre compilado e rodar direto no SGBD.
Bancos mais antigos como o SQL Server e Oracle possuem implementação há muito tempo.
MySQL, apenas a partir da versão 5.
Como qualquer outro programa, uma SP contém:
Entrada
Processamento
Saída
Onde:
Entrada: Recebe argumentos (partindo de zero);
Processamento: Realiza as ações programadas, dependentes dos argumentos inseridos ou não;
Saída: Retorna o resultado do processamento (pode ser um retorno vazio ou especificado).
No teu caso, para cada faixa, você pode fazer um select count, para determinar a quantidade de pessoas naquela faixa etária.
Depois, concatena o resultado numa variável e retorna ela.
Nem precisa de SQL enorme (não mexi na lógica do cálculo de idade, mas acho que dá para otimizar isso):
SELECT
CASE WHEN (YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5)) < 20 then '<20'
ELSE Trunc((YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))/5)*5
END as Faixa_de_idade,
Count(*)
FROM pessoas
GROUP BY 1
Bem simples isso, utilize uma clausula WHERE no seu select incluindo BETWEEN idade1 and idade2 e adicione um COUNT() para que te retorne a quantidade de pessoas em cada faixa de idade.
Por exemplo:
SELECT
COUNT(pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))) AS idade
FROM
pessoas
WHERE pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))
BETWEEN parametro1 and parametro2
Essa sentença funcionou depois que fiz uma pequena mudança nela
SELECT
pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5)) AS idade
FROM
pessoas
WHERE (YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))
BETWEEN 45 and 55
Porém eu teria que repeti-la para cada intervalo de idade, acho q pode ser mais otimizado, mas já é um bom começo.
Eu removi o Trunc(o mysql workbench falou q tal função não existia) e removi a multiplicação por 5 no final do else e a sentença funcionou trazendo os seguintes resultados
Faixa de idade - Quant Pessoas
35.0000 - 2
37.0000 - 1
42.0000 - 1
46.0000 - 1
49.0000 - 1
61.0000 - 1
64.0000 - 1
65.0000 - 1
80.0000 - 1
83.0000 - 1
<20 - 1
Foi bem feita a sentença, porém como eu nunca tinha usado CASE e END numa sentença sql, fiquei meio sem entender o q aconteceu, agora tenho q tentar agrupar o resultado dentro das faixas de idade, em vez de categorizar por cada idade
o .25 corresponde ao chorinho de um dia dos anos bissextos…
Então… no caso, como você quer agrupar por faixas ficaria tipo assim:
select case when trunc((curdate() - pes_data_nascimento) / 365.25) <= 20 then
'ate 20'
when trunc((curdate() - pes_data_nascimento) / 365.25) between 25 and 30 then
'de 25 a 30'
when trunc((curdate() - pes_data_nascimento) / 365.25) between 31 and 35 then
'de 31 a 35
...
end as faixa_idade
, count(*)
from pessoas
group by 1
Veja se o trunc não existe mesmo, deve ter outra função no lugar dele pra pegar só a parte inteira do resultado da operação
Por esse motivo havia sugerido stored procedure.
Você conseguiria criar os selects isoladamente e, ao fim, concatenar todos os resultados em uma única saída, formatada.
Talvez um cursor já resolvesse, também.
Enfim, há várias formas de se resolver isto, o ideal é que você foque em uma e vá até o fim com ela.
Dúvidas, poste aqui.
[quote=drsmachado][quote=ADEMILTON]A solução dada pelo evefuji é a mais eficiente de todas. Vou só tentar contribuir com o modo como fazemos cálculo de idade aqui:
[quote=fabiobh][quote=ManoJava]
Bem simples isso, utilize uma clausula WHERE no seu select incluindo BETWEEN idade1 and idade2 e adicione um COUNT() para que te retorne a quantidade de pessoas em cada faixa de idade.
SELECT
COUNT(pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))) AS idade
FROM
pessoas
WHERE pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))
BETWEEN parametro1 and parametro2
[/quote]
Essa sentença funcionou depois que fiz uma pequena mudança nela
SELECT
pes_nom_completo,pes_data_nascimento,(YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5)) AS idade
FROM
pessoas
WHERE (YEAR(CURDATE())-YEAR(pes_data_nascimento)) - (RIGHT(CURDATE(),5)<RIGHT(pes_data_nascimento,5))
BETWEEN 45 and 55
Porém eu teria que repeti-la para cada intervalo de idade, acho q pode ser mais otimizado, mas já é um bom começo.
Eu removi o Trunc(o mysql workbench falou q tal função não existia) e removi a multiplicação por 5 no final do else e a sentença funcionou trazendo os seguintes resultados
Faixa de idade - Quant Pessoas
35.0000 - 2
37.0000 - 1
42.0000 - 1
46.0000 - 1
49.0000 - 1
61.0000 - 1
64.0000 - 1
65.0000 - 1
80.0000 - 1
83.0000 - 1
<20 - 1
Foi bem feita a sentença, porém como eu nunca tinha usado CASE e END numa sentença sql, fiquei meio sem entender o q aconteceu, agora tenho q tentar agrupar o resultado dentro das faixas de idade, em vez de categorizar por cada idade
[/quote]
Otimização é a palavra chave, apesar que a diferença de performance é imperceptível, mas sempre é recomendado resumir ao maximo as sentenças, lógico que respeitando sempre as limitações de cada BD.
a soluçao do ADEMILTON teria sido ideal se eu tivesse conseguido fazer funcionar,
eu não soube passar ela corretamente
o que eu posso estar escrevendo errado nesta sentença abaixo
select case when ((curdate() - pes_data_nascimento) / 365.25) <= 20 then
when ((curdate() - pes_data_nascimento) / 365.25) between 25 and 30 then
when ((curdate() - pes_data_nascimento) / 365.25) between 31 and 35 then
end as faixa_idade
, count(*)
from pessoas
group by 1
no mysql workbench acusa erro na linha 2 no ‘when’
Faz tempo que não mexo com mysql (agora estou mais com oracle e postgres), mas vou fazer umas observações:
No Oracle, quando você faz diferença de datas, ele retorna o número de dias, no mysql, como data é tratada no formato Unix, não é possível fazer essa diferença. (se me lembro bem)
Para cálculo de idade no Oracle, eu costumava usar a diferença de datas em meses. Se tiver uma função no MySQL que faça a diferença de datas e retorne em meses ou ano, seria melhor (e teria o melhor desempenho)
No mysql, se me lembro bem, é Floor. A ideia da lógica é “truncar” o número usando o valor de intervalos, segue um exemplo:
É mais rápido usar cálculos aritméticos que “case when”. No caso, coloquei só o valor inicial no Case When porque agrupa todos os valores menores que 20.
Edit: Acusa erro no segundo WHEN porque não colocou o valor que retorna no “THEN” anterior.
Como vc falou estava esquecendo o retorno, mas agora q coloquei funcionou.
Sim, o trunc não funciona no mysql, o floor resolve o problema.
Eu entendi sua logica, vou ver se consigo fazer o Mysql devolver o valor da data em anos para poder gerar essa sentença, caso não consiga a solução do case when funciona e eu vou tentar me virar com ela.
Obrigado a todos por ajudarem, a galera do GUJ detona mesmo, vlw e t+
Se o cara tiver mais de 100 anos vai dar diferença de 1 dia. (a cada 100 anos não tem 1 dos anos bissextos, e a cada 1000 anos “volta” esse ano bissexto que não deveria ter)
1 - criaria uma tabela temporaria …
2 - nesta tabela tem tudo que preciso …
da uma olhada no exemplo que fiz, ver se ajuda !!!
drop table if exists tempgrupoidade;
create table tempgrupoidade
Select apelido, dtnascimento, (DATEDIFF(NOW(), dtnascimento) / 365.25) as idade from flfuncionarios;
alter table tempgrupoidade add grupo int(10);
update tempgrupoidade set grupo = 1 where idade < 20;
update tempgrupoidade set grupo = 2 where idade between 20 and 31;
update tempgrupoidade set grupo = 3 where idade between 32 and 51;
update tempgrupoidade set grupo = 4 where idade between 52 and 71;
update tempgrupoidade set grupo = 5 where idade > 72;
select * from tempgrupoidade;