Publicidade   
 você está aqui: phpbrasil.com    artigos    artigo  
 
:: novos artigos ::

:: recomendado ::

Fundamentos de PHP

Compre esse livro no Submarino.com.br

:: publicidade ::


:: novos scripts ::

:: elenco phpbrasil ::

rafaelgh2005
Pontos: 3092

Visite a página de perfil de Emanuel FonsecaConsultas complexas utilizando processamento condicional no MySql.
por Emanuel Fonseca
Lista de Categorias  |  Contribua um Novo Artigo  |  Entre em Contato Conosco

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.
Vote aqui!
Média de Votos Atual: 9.28
Total de Votos: 60
Nota:   

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 = $dia

Esta 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.



<< Anterior 1 2 Próxima >>

 
Imprimir  |  Enviar para um Amigo


Comentários de Usuários

Boa
publicado por Newton Wagner - 2003-12-18 13:19:04

Boa a idéia e o artigo também!! Seria bom se postassem mais artigos sobre o SQL/mySQL. Valeu ae!

Um Pequeno Problema
publicado por mthiago - 2003-12-19 07:47:06

Quando você está tentando comparar se uma data vem antes ou depois da outra utilizando dia, mes e ano separados, é meio difícil conseguir o resultado correto utilizando apenas 2 ifs. Para você acreditar nisso, podemos lançar um exemplo onde a data de expiração de um usuário seja 01/12/2003 (dd/mm/yyyy) e a data atual seja 15/11/2003
Neste caso o usuário ainda está ativo. Mas este select retorna o resultado que ele já está cancelado. pois ('2003' = '2003' and '12' >= '11' and '01' >= '15') vai retornar "0".
O correto seria por no select ->
IF(expiraano > '$ano', 1, 0) as ano,
IF(expiraano = '$ano' and expirames > '$mes', 1, 0) as mes,
IF(expiraano = '$ano' and expirames = '$mes' and expiradia > '$dia', 1, 0) dia

e no having colocar ->
ano = 1 or mes = 1 or dia = 1

Mas a idéia é boa...





qual data vem antes uma data usando os três campos, é meio difícil de conseguir o result

Complemento!
publicado por mthiago - 2003-12-19 08:02:10

Só para complementar a minha resposta vou enviar uma outra forma (matemárica) de obter o mesmo resultado se os campos das colunas forem numéricos.

Select * from clientes where expiradia + (32 * expirames) + (366 * expiraano) > $dia + (32 * $mes) + (366 * $ano)

Espero ter ajudado!

Re: Um Pequeno Problema
publicado por Emanuel Fonseca - 2003-12-19 14:50:28

Na verdade existem formas mais simples como por exemplo curdate. Isso foi um exemplo. Mas se você observar o exemplo que você deu dá na mesma. O outro também está errado.


curdate
publicado por blesschild - 2003-12-22 07:23:37

Oq é curdate? Função do php? Eu não achei nada sobre ela ...

WHERE + HAVING ??
publicado por blesschild - 2003-12-22 07:39:39

Queria saber se a ordem dos fatores esta correta no sql abaixo e tb queria saber se vai funcionar o select com where e having, por acaso eu terei que colcoar tudo para having ou where, o artigo acima diz que este if funcionou melhor com having ...

"select count(n.IDNoticia) as id,IF('$t_date'>=n.Data_fim,0,1) as espira from noticias as n, categoria as c, usuarios as u where n.IDCat=c.IDCat and n.IDUser=u.IDUser and n.Publicar='1' and n.Data_fim>='$t_date' and n.Indice='1' ".$sqlcat." order by n.Data_inicio DESC";

Re: WHERE + HAVING ??
publicado por blesschild - 2003-12-22 07:50:32

Sorry, colei errado o sql:

"select count(n.IDNoticia) as id,IF(n.Data_fim<='$t_date',0,1) as expira from noticias as n, categoria as c, usuarios as u having expira='0' where n.IDCat=c.IDCat and n.IDUser=u.IDUser and n.Publicar='1' and and n.Indice='1' ".$sqlcat." order by n.Data_inicio DESC";

Re: Re: WHERE + HAVING ??
publicado por Emanuel Fonseca - 2003-12-23 06:32:49

Você testou? Explica qual o resultado você deseja.

Bom artigo..
publicado por Marcelo Pereira Fonseca da Silva Esse usuário pertence aos 10 usuários mais ativos do site - 2003-12-25 18:01:46

Legal o artigo..

Eu estou acostumado a usar case when ()

uma sintaxe um pouco diferente que é usada em bancos como o Oracle e o SQL Server..

$sql = "SELECT campo1, campo2, (CASE WHEN campo = 'Y' THEN
'S'
CASE WHEN campo = 'X' THEN
'N' END) as campo3
FROM tabela_feliz";

Re: curdate
publicado por Italo Marcelo de O. Costa Esse usuário pertence aos 10 usuários mais ativos do site - 2003-12-26 12:14:21

Curdate é uma função que retorna data corrente do sistema

Outra forma
publicado por Keylly Eyglys - 2003-12-28 12:28:54

Gosto de trabalhar com datas no formato Unix INT(14). Ajuda muito em comparações e em casos desse tipo.

Geralmente não é necessário usar consultas muito complexas para obter o resultado desejado.

Concatene as datas
publicado por Fábio Gonçalves - 2003-12-31 08:00:03

A melhor solução é concatenar as datas ano+mes+dia, assim você terá mais facilidade para comparar e não vai condicionar a sua instrução. O próprio MySql organiza as datas desta forma.

...
publicado por Emanuel Fonseca - 2004-01-04 15:05:26

O intuito do artigo é a syntax do if.

IF
publicado por Cléver Anjos Esse usuário pertence aos 10 usuários mais ativos do site - 2004-01-19 07:35:22

Uma utilização interessante é trazer algum valor de colunas que admitem NULL.

Exemplo :

SELECT nome, IF ( endereco is null, "Endereco nao preenchido", endereco) FROM enderecos ORDER BY nome


IFNULL
publicado por marcello_a - 2004-01-27 07:18:01

Cléver, acho que para esse caso seria melhor usar a função IFNULL(expr1,expr2), que retorna a expressão 1 se ela não for NULL; se for, retorna EXPR2.

Outro estrutura bem útil é o CASE, primeiro tópico da página de funções de controle de fluxo na página de ajuda do MySQL.

Usando condicionais para fazer join
publicado por marcello_a - 2004-01-27 07:20:26

Aproveitando a deixa, não sei se estou usando corretamente o espaço, mas comumente me deparo com o seguinte problema: uma tabela de clientes, com um bit indicando se é pessoa física ou jurídica; outras 2 tabelas (uma para PF outra para PJ) com os dados específicos de cada uma.

Existe alguma maneira de indicar no operador condicional, para mais de um registro no retorno, dizer para qual tabela o MySQL deve fazer o join para cada registro?

Maneira mais simples
publicado por xDeCo - 2005-07-15 07:23:55

Pega os 3 campos e concatena com CONCAT(), depois usa o comando DATE() para o mysql considerar e formatar como uma data, depois é só comparar com a data atual CURDATE().

SELECT * FROM clientes
WHERE DATE( CONCAT( ano , '-' , mes , '-' , dia ) ) > CURDATE();

Isso vai retornar todos os clientes que expiram de amanhã para frente...

Se quiser com mais tempo
> CURDATE() + INTERVAL 1 MONTH

etc...

Esse artigo é Salva Emprego.
publicado por huan_c3cria - 2005-07-17 18:35:32

Cara, esse artigo veio em boa hora... Queria fazer a mesma coisa que você fez.
Aqui deu tudo certo.

Abraços

Buenas...
publicado por gm_nununo - 2007-01-19 15:28:27

Muito menos matematico, se você tem três campos para UMA data... Por que não usar o concat na hora de comparar?

Por exemplo:

select * from clinetes concat(anoexpira,'-',$mesexpira,'-',diaexpira) >= curdate()

Testei no mySql 5.0, talvez em versões anteriores você precise usar o cast junto com o concat...

Grande Abraço
=NuNuNO==
( Que adora usar o IF em consultas, mas usa de outras formas... )

PS: É muito recomendado utilizar o tipo DATE do mySQL ao inves de trÊs campos integer...

Showwwwwwwwww
publicado por fccd - 2008-01-12 10:20:49

Que legal esse artigo...


Show

Publique os seus Comentários

Nome:
Email:
Título:
Comentário:

NOTA: Cadastre-se no site para poder publicar comentários.

 
webmaster: João Prado Maia   © 2000 - 2005 phpbrasil.com
Gerado em 0.169 segundos