Ir para conteúdo

POWERED BY:

Arquivado

Este tópico foi arquivado e está fechado para novas respostas.

doido

Gerar Resultado Entre Datas mesmo sem registros

Recommended Posts

Olá,

 

Possuo uma tabela que mostra o serviço de alguns técnicos. Eu tenho um SELECT que retornar a quantidade de serviços de cada técnico no intervalo de dias, exemplo:

 

SELECT nome_tecnico, COUNT(*) FROM _TBL_SERVICOS WHERE data BETWEEN "2015-01-01" AND "2015-01-31" GROUP BY data,nome_tecnico ORDER BY data,nome_tecnico

 

Até ai tudo bem, mas o problema é que se um técnico não tiver trabalhado naquele dia, ele não aparece no dia em questão. Agora preciso exibir todos os dias, com todos os técnicos, para saber se o cara faltou.

 

Minha solução foi usar o UNION ALL, exemplo:

 

SELECT COUNT(*) FROM _TBL_SERVICOS WHERE nome_tecnico = "FULANO" AND data = "2015-01-01"

UNION ALL

SELECT COUNT(*) FROM _TBL_SERVICOS WHERE nome_tecnico = "FULANO" AND data = "2015-01-02"

UNION ALL

...

SELECT COUNT(*) FROM _TBL_SERVICOS WHERE nome_tecnico = "FULANO" AND data = "2015-01-31"

UNION ALL

SELECT COUNT(*) FROM _TBL_SERVICOS WHERE nome_tecnico = "FULANO2" AND data = "2015-01-01"

UNION ALL

SELECT COUNT(*) FROM _TBL_SERVICOS WHERE nome_tecnico = "FULANO2" AND data = "2015-01-02"

UNION ALL

...

 

Só que o comando fica enorme. Imagina para 30 técnicos, cada técnico teria 31 selects (referentes a 31 dias) X 30 técnicos. Alguém teria alguma solução ai mais enxuta????

 

Desde já agradeço a atenção

Compartilhar este post


Link para o post
Compartilhar em outros sites

Motta, eu estou tentando o seguinte comando:

SELECT _TBL_TECNICOS.nome AS tecnico, _TBL_AGENDAMENTOS.agexecucao, COUNT(_TBL_AGENDAMENTOS.agexecucao) AS total FROM _TBL_TECNICOS  LEFT OUTER JOIN _TBL_AGENDAMENTOS ON_TBL_TECNICOS.id_tecnicos = _TBL_AGENDAMENTOS.id_tecnicos AND _TBL_AGENDAMENTOS.agexecucao BETWEEN "2015-03-05" AND "2015-03-05" AND_TBL_AGENDAMENTOS.empresa = 1 AND _TBL_AGENDAMENTOS.execucao <> "" WHERE _TBL_TECNICOS.ativo = "S" AND _TBL_TECNICOS.empresa = 1GROUP BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nome ORDER BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nome

Dessa forma, eu faço o contrário... ao invés de localizar os serviços (agendamentos) e conferir quais técnicos os fizeram, eu estou listando todos os técnicos ATIVOS da Empresa 1, e depois checando se eles tem algum serviço nesse dia (repara que eu usei o intervalo entre o dia 05/03 até o mesmo dia, agexecucao é o campo da data do serviço). O problema é que se ele não tiver, a data aparece nula e me atrapalha para ordenar em intervalos de dias maiores que 1, por exemplo, do dia 05 até dia 15.

 

Me desculpe, mas eu não entendi muito bem o que foi feito lá naquele topico que me mandou, poderia me explicar? Com esse detalhamento maior que te passei, encaixa na solução???

 

Abraços e desde já agradeço a atenção

Compartilhar este post


Link para o post
Compartilhar em outros sites

o que faço e um union dos casos que existem e tem valores com os casos possíveis forçando um valor zerado , faço um sum com group by e tenho todos os casos ainda que zerados

 

um exemplos simples (vendas)

select nome_vendedor , sum(valor_venda) total --soma vendas
from vendedores , vendas
where vendedores.cod = vendas.cod
group by nome_vendedor
union all
select nome_vendedor , 0 total --lista vendedores com valor zero
from vendedores

"junta" isto

select nome_vendedor , sum(total) total
from
(
select nome_vendedor , sum(valor_venda) total --soma vendas
from vendedores , vendas
where vendedores.cod = vendas.cod
group by nome_vendedor
union all
select nome_vendedor , 0 total --lista vendedores com valor zero
from vendedores
)
group by nome_vendedor

exemplo simples , mas a ideia básica é esta

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na verdade vc vai precisar de um left join

 

primeiro vc gera uma "lista" com todos os funcionarios e datas possiveis e depois faz left join com a tabela atual , assim as que não tiverem dados simplesmente aparecerao nulas, mas aparecerao e vc pode fazer um ifnull ='faltou'

Compartilhar este post


Link para o post
Compartilhar em outros sites

Saquei, ao meu ver eu fiz parecido com a sua idéia do UNION ALL para os que não apareciam os valores, o problema é que eu tinha um intervalo de datas, e nesses intervalos que ficavam alguns em brancos, e ficaram muitos SELECTs pois eu precisava ordenar por essa data...

 

Mas agora consegui reduzir drasticamente o numero de linhas do comando, antes estava dando um SELECT de 10.000 linhas, agora caiu para 280...

 

Fiz o seguinte, vê ai o raciocínio. Tentei aplicar esse comando para reduzir os SELECTs, faria isso por dia:

 

SELECT _TBL_TECNICOS.nome AS tecnico, _TBL_AGENDAMENTOS.agexecucao, COUNT(_TBL_AGENDAMENTOS.agexecucao) AS total FROM _TBL_TECNICOS LEFT OUTER JOIN _TBL_AGENDAMENTOS ON
_TBL_TECNICOS.id_tecnicos = _TBL_AGENDAMENTOS.id_tecnicos AND _TBL_AGENDAMENTOS.agexecucao = "2015-03-01" AND _TBL_AGENDAMENTOS.empresa = 1 AND _TBL_AGENDAMENTOS.execucao <> "" WHERE _TBL_TECNICOS.ativo = "S" AND _TBL_TECNICOS.empresa = 1
GROUP BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nome
ORDER BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nome

 

Ai tinha problemas para ordenar, pois quem nao trabalhou nessa data o agexecucao vinha NULL, e depois para ordenar ficava complicado, ai matei criando um campo chamado ordem com valor fixo. Assim:

SELECT DATE("2015/03/01") AS ordem, _TBL_TECNICOS.nome AS tecnico, COUNT(_TBL_AGENDAMENTOS.id_agendamentos) AStotal,(SELECT COUNT(T1.id_agendamentos) FROM _TBL_AGENDAMENTOS T1 WHERE T1.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T1.agexecucao ="2015/03/01" AND T1.execucao <> ""  AND T1.empresa = 1) AS baixados,(SELECT COUNT(T2.id_agendamentos) FROM _TBL_AGENDAMENTOS T2 WHERE T2.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T2.agexecucao ="2015/03/01" AND T2.execucao <> "CANCELADO" AND T2.execucao <> "REAGENDADO" AND T2.execucao <> ""  ANDT2.empresa = 1) AS ok,(SELECT max(T3.horabaixa) FROM _TBL_AGENDAMENTOS T3 WHERE T3.agexecucao = "2015/03/01" AND T3.id_tecnicos =_TBL_TECNICOS.id_tecnicos  AND T3.empresa = 1) AS horabaixafinalFROM _TBL_TECNICOS LEFT OUTER JOIN _TBL_AGENDAMENTOS ON _TBL_TECNICOS.id_tecnicos = _TBL_AGENDAMENTOS.id_tecnicos AND_TBL_AGENDAMENTOS.agexecucao = "2015/03/01" AND _TBL_AGENDAMENTOS.empresa = 1 WHERE_TBL_TECNICOS.ativo = "S" AND _TBL_TECNICOS.empresa = 1 GROUP BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nomeUNION ALL
SELECT DATE("2015/03/02") AS ordem, _TBL_TECNICOS.nome AS tecnico, COUNT(_TBL_AGENDAMENTOS.id_agendamentos) AS total, (SELECT COUNT(T1.id_agendamentos) FROM _TBL_AGENDAMENTOS T1 WHERE T1.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T1.agexecucao = "2015/03/02" AND T1.execucao <> "" AND T1.empresa = 1) AS baixados, (SELECT COUNT(T2.id_agendamentos) FROM _TBL_AGENDAMENTOS T2 WHERE T2.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T2.agexecucao = "2015/03/02" AND T2.execucao <> "CANCELADO" AND T2.execucao <> "REAGENDADO" AND T2.execucao <> "" AND T2.empresa = 1) AS ok, (SELECT max(T3.horabaixa) FROM _TBL_AGENDAMENTOS T3 WHERE T3.agexecucao = "2015/03/02" AND T3.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T3.empresa = 1) AS horabaixafinal FROM _TBL_TECNICOS LEFT OUTER JOIN _TBL_AGENDAMENTOS ON _TBL_TECNICOS.id_tecnicos = _TBL_AGENDAMENTOS.id_tecnicos AND _TBL_AGENDAMENTOS.agexecucao = "2015/03/02" AND _TBL_AGENDAMENTOS.empresa = 1 WHERE _TBL_TECNICOS.ativo = "S" AND _TBL_TECNICOS.empresa = 1 GROUP BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nomeUNION ALL 

...

Com isso pego todos os tecnicos do dia 01,uso um UNION ALL para os outros dias do intervalo de datas, dia 02, dia 03 e assim ai, enxuguei bastante pois antes dava um select para cada tecnico em cada dia, não sei se consigo enxugar mais, caso alguém tenha uma idéia, sou todo ouvidos. Melhorei um pouco o código, segue abaixo:

SELECT DATE("2015/03/01") AS ordem, _TBL_TECNICOS.nome AS tecnico,(SELECT COUNT(T1.id_agendamentos) FROM _TBL_AGENDAMENTOS T1 WHERE T1.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T1.agexecucao ="2015/03/01" AND T1.empresa = 1) AS total,(SELECT COUNT(T2.id_agendamentos) FROM _TBL_AGENDAMENTOS T2 WHERE T2.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T2.agexecucao ="2015/03/01" AND T2.execucao <> ""  AND T2.empresa = 1) AS baixados,(SELECT COUNT(T3.id_agendamentos) FROM _TBL_AGENDAMENTOS T3 WHERE T3.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T3.agexecucao ="2015/03/01" AND T3.execucao <> "CANCELADO" AND T3.execucao <> "REAGENDADO" AND T3.execucao <> ""  ANDT3.empresa = 1) AS ok,(SELECT max(T4.horabaixa) FROM _TBL_AGENDAMENTOS T4 WHERE T4.agexecucao = "2015/03/01" AND T4.id_tecnicos =_TBL_TECNICOS.id_tecnicos AND T4.empresa = 1) AS horabaixafinalFROM _TBL_TECNICOS WHERE _TBL_TECNICOS.ativo = "S" AND _TBL_TECNICOS.empresa = 1 GROUP BY _TBL_TECNICOS.id_tecnicosUNION ALLSELECT DATE("2015/03/02") AS ordem, _TBL_TECNICOS.nome AS tecnico,(SELECT COUNT(T1.id_agendamentos) FROM _TBL_AGENDAMENTOS T1 WHERE T1.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T1.agexecucao ="2015/03/02" AND T1.empresa = 1) AS total,(SELECT COUNT(T2.id_agendamentos) FROM _TBL_AGENDAMENTOS T2 WHERE T2.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T2.agexecucao ="2015/03/02" AND T2.execucao <> ""  AND T2.empresa = 1) AS baixados,(SELECT COUNT(T3.id_agendamentos) FROM _TBL_AGENDAMENTOS T3 WHERE T3.id_tecnicos = _TBL_TECNICOS.id_tecnicos AND T3.agexecucao ="2015/03/02" AND T3.execucao <> "CANCELADO" AND T3.execucao <> "REAGENDADO" AND T3.execucao <> ""  ANDT3.empresa = 1) AS ok,(SELECT max(T4.horabaixa) FROM _TBL_AGENDAMENTOS T4 WHERE T4.agexecucao = "2015/03/02" AND T4.id_tecnicos =_TBL_TECNICOS.id_tecnicos AND T4.empresa = 1) AS horabaixafinalFROM _TBL_TECNICOS WHERE _TBL_TECNICOS.ativo = "S" AND _TBL_TECNICOS.empresa = 1 GROUP BY _TBL_TECNICOS.id_tecnicos UNION ALL 

...

 

Abraços a todos

 

Obrigado Motta

Compartilhar este post


Link para o post
Compartilhar em outros sites

Na verdade você vai precisar de um left join

 

primeiro você gera uma "lista" com todos os funcionarios e datas possiveis e depois faz left join com a tabela atual , assim as que não tiverem dados simplesmente aparecerao nulas, mas aparecerao e você pode fazer um ifnull ='faltou'

Então, foi isso que fiz. Mas o faltou ali me "quebrou" na hora de ordenar, por isso criei o campo ORDEM jogando as datas manualmente.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Bem, vou marcar como resolvido, pois enxuguei bastante o código, de 10.000 linhas para 280 com a idéia que tive da coluna ORDEM com valores fixos.

Compartilhar este post


Link para o post
Compartilhar em outros sites

×

Informação importante

Ao usar o fórum, você concorda com nossos Termos e condições.