Ir para conteúdo

POWERED BY:

Arquivado

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

emanuel fonseca

Consultas complexas usando IF no MySql!

Recommended Posts

Em determinados momentos de nossa carreira, a necessidade nos leva a quebrar certos vícios habituais, como as boas e velhas consultas à banco de dados. Acredito que a grande maioria, com o tempo adquire este mau hábito e assim tornando mais difícil sua evolução pessoal. Há algumas semanas me deparei com um sistema que realmente me consumiu dias a procura de uma solução eficaz e definitiva. Tomaremos esta como exemplo, para que de alguma forma ajudar todos aqueles que se depararem com este tipo de problema.Abaixo apresento a solução que encontrei e descrevo sua utilização e sintaxe.SELECT *,IF(expiraano = '$ano' and expirames >= '$mes' and expiradia >= '$dia', 0, 1) as presente, IF(expiraano > '$ano', 2,3) as futuro from clientes having presente = '0' or futuro = '2'Eu precisava fazer um relatório de clientes ativos. Eu tinha 03 campos no BD: Um que equivale ao ano de vencimento, outro que equivalia ao mês de vencimento e outro que equivalia ao dia de vencimento. Basicamente iniciei pelo mais fácil, que era comparar valores através de where. Porém tornou-se meramente impossível, adotar este tipo de comparação, pois sempre retornaria registros de forma não pertinente ao resultado que necessitava. A minha primeira tentativa (vicio) foi utilizar o exemplo: SELECT * FROM clientes where expiraano >= $ano and expirames >= $mes and expiradia = $diaEsta clausula retornava valores, porém com alguns erros. Ela listava apenas o mês seguinte (no caso de se tratar do mês 12) e mesmo assim os dias não conferiam, tornando nossos resultados totalmente infiéis à realidade. E qual a solução a ser aplicada, diante desta incógnita? Seria fazer uma consulta anterior e utilizar processamento condicional para exibir os dados. Certo! Realmente funcionaria, porém havia um outro problema: A paginação dos dados. Então fui à caça de soluções alternativas, e comecei a vasculhar a documentação do banco de dados (que também não ajuda muito, já que é bem simplória em termos de exemplos). Já conhecia esta implementação para controle de fluxo, porém não sabia que poderia aplica - lá em conjunto com consultas em tabelas (como disse a documentação é pobre no sentido). Depois de inúmeras tentativas, cheguei ao resultado desejado conforme descreverei abaixo: SELECT * (Até aqui esta tudo bem, não muda em nada o select habitual),IF(expiraano = '$ano' and expirames >= '$mes' and expiradia >= '$dia', 0, 1) as presente, Aqui adotamos então a primeira avaliação condicional. Se vocês notarem a virgula antes do "IF", notarão que nosso controle de fluxo toma forma de campo. Dentro do "IF" fazemos comparações até que habituais, porém esta é a parte mais importante da nossa consulta. Notem que a estrutura do "IF" é dividida em 3 partes: IF(expression,then,else). Onde o que está antes da primeira vírgula, caso retorne verdadeiro (true) esse campo tomará o valor especificado e/ou expressão que esta após a primeira vírgula (0). Caso nossa expressão antes da primeira vírgula retorne false , nosso campo tomará o valor e/ou expressão que esta após a segunda vírgula (1). Por fim criaremos um alias para este novo campo , através de "as nomedocampo". Se não tivermos este cuidado nosso campo terá o mesmo nome que a condicional, ou seja, terá o nome "IF(expiraano = '$ano' and expirames >= '$mes' and expiradia >= '$dia', 0, 1)".Agora vamos a segunda condicional:,IF(expiraano > '$ano', 2,3) as futuro Na segunda avaliação procedemos com outra comparação, e como foi visto anteriormente se esta for verdadeira retornará o campo tomará como valor o que segue após a primeira virgula e se for falsa terá como valor o que segue após a segunda virgula. Criamos um alias para nosso novo campo no Banco de dados.Tudo bem conseguimos construir nossa cláusula e agora precisamos filtrar os resultados obtidos. Normalmente utilizaríamos o nosso costumeiro where, porém existem restrições quanto sua utilização neste tipo de consulta. Pois bem, nossa saída então foi encontrar uma outra forma conforme descrevo abaixo.from clientes having presente = '0' or futuro = '2' Utilizamos a cláusula having, que para casos específicos (if, case e group by) substitui o where.Acredito que a grande maioria tenha entendido esse artigo, porém para aqueles que ainda sentem dificuldades irei grafar um exemplo mais direto.Dado:Dia atual = 16;Mês atual = 12;Ano atual = 2003;SELECT *,IF(expiraano = '2003' and expirames >= '12' and expiradia >= '16', 0, 1) as presente, IF(expiraano > '2003’, 2,3) as futuro from clientes having presente = '0' or futuro = '2'Na nossa primeira condicional, lê-se:Se o campo expiraano for igual ao ano atual e o campo expirames for maior ou igual ao mês atual e o campo expiradia for maior ou igual ao dia atual este campo terá “0” como valor, caso contrário terá “1” como valor.Na nossa segunda lê – se:Se o campo expiraano for maior que o ano atual este campo terá “2” como valor, caso contrário terá “3” como valor. Seguindo o que foi proposto, o campo presente terá valores “0” e valores “1” e o campo futuro terão valores “2” e valores “3”. Se vocês observaram, logo notaram que utilizamos or e não and quando filtramos os dados. Mas pq? Notem que se utilizarmos o and, a select retornará 0 resultados, pois uma consulta depende da outra pq a segunda depende dos resultados que retornarem false da primeira.Espero que este artigo tenha serventia para vocês e que os ajudem a solucionar problemas semelhantes a este.[]'sEmanuel Fonseca

Compartilhar este post


Link para o post
Compartilhar em outros sites

com um pouquinho mais de knowledgement você teria chegado a essa query:

 

> SELECT * from teste WHERE TO_DAYS(CONCAT(expiraano,"-",expirames,"-",expiradia)) >= TO_DAYS(CURDATE())

> 5 Field(s), 25497 Record(s). Time: 0.92 sec.

 

ao invés dessa:

 

> SELECT *,IF(expiraano = '2003' and expirames >= '12' and expiradia >= '18', 0, 1) as presente, IF(expiraano > '2003', 2,3) as futuro from teste having presente = '0' or futuro = '2'

> 7 Field(s), 25497 Record(s). Time: 1.68 sec.

Compartilhar este post


Link para o post
Compartilhar em outros sites

Em determinados momentos de nossa carreira, a necessidade nos leva a quebrar certos vícios habituais, como as boas e velhas consultas à banco de dados. Acredito que a grande maioria, com o tempo adquire este mau hábito e assim tornando mais difícil sua evolução pessoal. Há algumas semanas me deparei com um sistema que realmente me consumiu dias a procura de uma solução eficaz e definitiva. Tomaremos esta como exemplo, para que de alguma forma ajudar todos aqueles que se depararem com este tipo de problema.Abaixo apresento a solução que encontrei e descrevo sua utilização e sintaxe.SELECT *,IF(expiraano = '$ano' and expirames >= '$mes' and expiradia >= '$dia', 0, 1) as presente, IF(expiraano > '$ano', 2,3) as futuro from clientes having presente = '0' or futuro = '2'Eu precisava fazer um relatório de clientes ativos. Eu tinha 03 campos no BD: Um que equivale ao ano de vencimento, outro que equivalia ao mês de vencimento e outro que equivalia ao dia de vencimento. Basicamente iniciei pelo mais fácil, que era comparar valores através de where. Porém tornou-se meramente impossível, adotar este tipo de comparação, pois sempre retornaria registros de forma não pertinente ao resultado que necessitava. A minha primeira tentativa (vicio) foi utilizar o exemplo: SELECT * FROM clientes where expiraano >= $ano and expirames >= $mes and expiradia = $diaEsta clausula retornava valores, porém com alguns erros. Ela listava apenas o mês seguinte (no caso de se tratar do mês 12) e mesmo assim os dias não conferiam, tornando nossos resultados totalmente infiéis à realidade. E qual a solução a ser aplicada, diante desta incógnita? Seria fazer uma consulta anterior e utilizar processamento condicional para exibir os dados. Certo! Realmente funcionaria, porém havia um outro problema: A paginação dos dados. Então fui à caça de soluções alternativas, e comecei a vasculhar a documentação do banco de dados (que também não ajuda muito, já que é bem simplória em termos de exemplos). Já conhecia esta implementação para controle de fluxo, porém não sabia que poderia aplica - lá em conjunto com consultas em tabelas (como disse a documentação é pobre no sentido). Depois de inúmeras tentativas, cheguei ao resultado desejado conforme descreverei abaixo: SELECT * (Até aqui esta tudo bem, não muda em nada o select habitual),IF(expiraano = '$ano' and expirames >= '$mes' and expiradia >= '$dia', 0, 1) as presente, Aqui adotamos então a primeira avaliação condicional. Se vocês notarem a virgula antes do "IF", notarão que nosso controle de fluxo toma forma de campo. Dentro do "IF" fazemos comparações até que habituais, porém esta é a parte mais importante da nossa consulta. Notem que a estrutura do "IF" é dividida em 3 partes: IF(expression,then,else). Onde o que está antes da primeira vírgula, caso retorne verdadeiro (true) esse campo tomará o valor especificado e/ou expressão que esta após a primeira vírgula (0). Caso nossa expressão antes da primeira vírgula retorne false , nosso campo tomará o valor e/ou expressão que esta após a segunda vírgula (1). Por fim criaremos um alias para este novo campo , através de "as nomedocampo". Se não tivermos este cuidado nosso campo terá o mesmo nome que a condicional, ou seja, terá o nome "IF(expiraano = '$ano' and expirames >= '$mes' and expiradia >= '$dia', 0, 1)".Agora vamos a segunda condicional:,IF(expiraano > '$ano', 2,3) as futuro Na segunda avaliação procedemos com outra comparação, e como foi visto anteriormente se esta for verdadeira retornará o campo tomará como valor o que segue após a primeira virgula e se for falsa terá como valor o que segue após a segunda virgula. Criamos um alias para nosso novo campo no Banco de dados.Tudo bem conseguimos construir nossa cláusula e agora precisamos filtrar os resultados obtidos. Normalmente utilizaríamos o nosso costumeiro where, porém existem restrições quanto sua utilização neste tipo de consulta. Pois bem, nossa saída então foi encontrar uma outra forma conforme descrevo abaixo.from clientes having presente = '0' or futuro = '2' Utilizamos a cláusula having, que para casos específicos (if, case e group by) substitui o where.Acredito que a grande maioria tenha entendido esse artigo, porém para aqueles que ainda sentem dificuldades irei grafar um exemplo mais direto.Dado:Dia atual = 16;Mês atual = 12;Ano atual = 2003;SELECT *,IF(expiraano = '2003' and expirames >= '12' and expiradia >= '16', 0, 1) as presente, IF(expiraano > '2003’, 2,3) as futuro from clientes having presente = '0' or futuro = '2'Na nossa primeira condicional, lê-se:Se o campo expiraano for igual ao ano atual e o campo expirames for maior ou igual ao mês atual e o campo expiradia for maior ou igual ao dia atual este campo terá “0” como valor, caso contrário terá “1” como valor.Na nossa segunda lê – se:Se o campo expiraano for maior que o ano atual este campo terá “2” como valor, caso contrário terá “3” como valor. Seguindo o que foi proposto, o campo presente terá valores “0” e valores “1” e o campo futuro terão valores “2” e valores “3”. Se vocês observaram, logo notaram que utilizamos or e não and quando filtramos os dados. Mas pq? Notem que se utilizarmos o and, a select retornará 0 resultados, pois uma consulta depende da outra pq a segunda depende dos resultados que retornarem false da primeira.Espero que este artigo tenha serventia para vocês e que os ajudem a solucionar problemas semelhantes a este.[]'sEmanuel Fonseca

Query took 0.0014 sec do meu jeito.Query took 0.0024 sec do outro jeito.Isso não é o importante, pois IF tem muito mais abrangencia e você pode utilizar de outras milhares de forma. Ja funções especificas não. Entenda o exemplo, pq o que discutimos aqui não é solução e sim utilização.

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.