doido 0 Denunciar post Postado Abril 1, 2015 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 645 Denunciar post Postado Abril 1, 2015 Veja se ajuda Compartilhar este post Link para o post Compartilhar em outros sites
doido 0 Denunciar post Postado Abril 1, 2015 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
Motta 645 Denunciar post Postado Abril 1, 2015 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
giesta 29 Denunciar post Postado Abril 1, 2015 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
doido 0 Denunciar post Postado Abril 1, 2015 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 = 1GROUP BY _TBL_AGENDAMENTOS.agexecucao, _TBL_TECNICOS.nomeORDER 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
doido 0 Denunciar post Postado Abril 2, 2015 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
doido 0 Denunciar post Postado Abril 2, 2015 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