sábado, 13 de novembro de 2010

Subconsultas em SQL

Olá denovo...
Depois de um tempo fora, to voltando agora com uma dica importante em sql...

Durante o processo de desenvolvimento de um site me deparei com a seguinte situação: eu precisava retornar os 5 maiores valores de uma coluna e ordená-los por outra coluna diferente, rapidamente pensei em usar o comando IN, ficaria assim:

SELECT `coluna_chave`,`coluna_1`,`coluna_2` FROM `tabela` WHERE `coluna_chave` IN (SELECT `coluna_chave`,`coluna_2` FROM `tabela` ORDER BY `coluna_2` DESC LIMIT 0,5) ORDER BY `coluna_1`;

Ou seja, na consulta dentro do comando "IN" ele faria uma busca na tabela ordenando pela coluna 2 e tendo como limit 5, ou seja, seriam mostrados os cinco maiores valores da coluna 2.
O SELECT principal retornaria as linhas cuja a `coluna_chave` encontravam-se na consulta dentro do "IN" (os 5 maiores valores) e depois ordenaria pela coluna 2.

Esse comando resolveria meu problema, porém o MYSQL não suporta o comando LIMIT dentro de um comando IN.

E passaram-se mais alguns minutos pensando até que cheguei num outro comando:

SELECT `coluna_chave`,`coluna_1`,`coluna_2` FROM (SELECT `coluna_chave`,`coluna_1`,`coluna_2` FROM `tabela` ORDER BY `coluna_2` DESC LIMIT 0,5) as `tabela_2` ORDER BY `coluna_1`;

Ou seja, resolvi colocar a subconsulta no lugar tabela. Sendo assim ele busca os resultados de uma tabela gerada por uma subconsulta (subconsulta essa que retorna somento os 5 maiores valores da coluna_2) e não pela tabela completa e podendo depois disso ordenar por uma outra coluna, neste caso pela coluna_2.

Ufa... finalmente problema resolvido. Comente aqui se você enfrentou algum problema semelhante e se isso ocorrem em outros bancos.

Espero ter ajudado, nos vemos outro dia.
Abraço

sexta-feira, 29 de outubro de 2010

Trabalhando data em PHP - TIMESTAMP

Antes de continuar com funções que manipulam data em PHP, eu vou definir o que é um TIMESTAMP, para que eu possa seguir usando esse termo sabendo que todos entenderão o que eu vou estar falando.

O timestamp é um número inteiro gerado apartir de datas, sendo o inteiro 0 igual ao dia 01/01/1970 00:00:00 e para cada segundo passado é acrescido 1 no valor inteiro. Ou seja:

0 = 01/01/1970 00:00:00
1 = 01/01/1970 00:00:01
2 = 01/01/1970 00:00:02
(...)
60 = 0 = 01/01/1970 00:01:00

O timestamp é muito útil para cálculo de datas por conseguir transforma uma data formatada em um número que pode ser aplicado qualquer cálculo algébrico.

As funções usadas para transformação são as seguintes:

De TIMESTAMP para data formatada:

strftime($format, $timestamp = null);

Sendo, $format é a formatação final da data. Usa-se %d para dias, %m para meses, %y para ano com 2 dígitos e %Y para ano com 4 dígitos.

E sendo, $timestamp o timestamp de origem que deseja-se transformar. Esse argumento é opcional, seu valor de ausência é o timestamp atual.

Ex.:
strftime ("%d/%m/%Y");

De DATA FORMATADA para timestamp:

mktime($hour, $minute, $second, $month, $day, $year);
Retorna o Timestamp da data e hora definida.....

Espero ter ajudado...
Abraço

terça-feira, 26 de outubro de 2010

Trabalhando data em PHP - 1

A partir de hoje vou começar uma série de posts com algumas das funções existentes no PHP usadas para cálculos e formatações com datas.

Hoje será mostrada a função srtotime.

A função strtotime é uma das mais úteis para cálculos com datas. Possui dois argumentos:

O primeiro mostra qual é o calculo a ser feito. Esse cálculo é mostrado no formato texto no idioma inglês. Para isso é usado um sinal (+ ou -) um número inteiro e a base do cálculo. Para a base são usadas as seguintes Palavras: "days" para dias, "months" para meses e "years" para anos. SEMPRE NO PLURAL mesmo que o número em questão sejo o 1.
Ex.:
"-3 days" ou +2 months" ou "+1 years".
Isso mesmo, só isso já suficiente para o cálculo.

O segundo argumento é o timestamp da data de origem a ser calculada. É opcional e seu valor de ausência é o timestamp da data atual.

O valor de retorno da função é um timestamp. Se for necessário mostrar em formato de data então usa-se outra função, mas isso é assunto para o próximo post.

Exemplos de aplicação da função:

strtotime('-1 days');
strtotime('+3 years');
strtotime('+2 months');
strtotime('+3 years', strtotime('-1 days'));

Cabeçalho da função: strtotime($time, $now=null);

Espero ter ajudado.. No próximo post será abordado a transformação de timestamp para formato de data e vice-versa.

terça-feira, 19 de outubro de 2010

Validação de CNPJ

Embora a validação de CPF já esteja bastante divulgado e documentada na internet, a validação de CNPJ já não é tão simples de ser encontrada, até mesmo por não ser tão utilizada.

Portanto segue a seguir primeiro a explicação depois o código em PHP de uma função de validação de CNPJ.

A validação funciona da seguinte maneira:

Primeiro dígito verificador....
(n1*5)+(n2*4)+(n3*3)+(n4*2)+(n5*9)+(n6*8)+(n7*7)+(n8*6)+(n9*5)+(n10*4)+(n11*3)+(n12*2)
Soma-se tudo e dividi por 11. Após isso, subtrai-se 11 do resto da divisão.
O resultado desta subtração é o primeiro dígito verificador. Caso ele seja maior que 9 então ele é igual a zero.

Para o segundo dígito verificador....
(n1*6)+(n2*5)+(n3*4)+(n4*3)+(n5*2)+(n6*9)+(n7*8)+(n8*7)+(n9*6)+(n10*5)+(n11*4)+(n12*3)+(d1*2)

Soma-se tudo e dividi por 11. Após isso, subtrai-se 11 do resto da divisão.
O resultado desta subtração é o segundo dígito verificador. Caso ele seja maior que 9 então ele é igual a zero.

Função em PHP:

function ValidaCNPJ ($cnpj){
$soma = ((5*$cnpj[0])+(4*$cnpj[1])+(3*$cnpj[2])+(2*$cnpj[3])+(9*$cnpj[4])+(8*$cnpj[5])+(7*$cnpj[6])+(6*$cnpj[7])+(5*$cnpj[8])+(4*$cnpj[9])+(3*$cnpj[10])+(2*$cnpj[11]));
$n1 = 11 - ($soma%11);
if ($n1 > 9) $n1 = 0;

$soma = ((6*$cnpj[0])+(5*$cnpj[1])+(4*$cnpj[2])+(3*$cnpj[3])+(2*$cnpj[4])+(9*$cnpj[5])+(8*$cnpj[6])+(7*$cnpj[7])+(6*$cnpj[8])+(5*$cnpj[9])+(4*$cnpj[10])+(3*$cnpj[11])+(2*$n1));
$n2 = 11 - ($soma%11);
if ($n2 > 9) $n2 = 0;

if (($n1 == $cnpj[12]) && ($n2 == $cnpj[13]))
return TRUE;
else return FALSE;
}

É isso... Espero que tenham gostado....

sábado, 16 de outubro de 2010

Validação de CPF

Embora para programadores mais experientes esse assunto seja redundante, para outros iniciantes pode ser útil, portanto segue o algoritmo de validação do CPF.

O CPF contém 11 números, sendo 9 deles definidos pela Receita Federal e os dois últimos verificadores.
Primeiro vou tentar mostrar como funciona o cálculo e depois posto uma função em PHP.

Pra facilitar usarei n1 como o primeiro dígito, n2 como o segundo e assim sucessivamente...

Para encontrar qual é o primeiro dígito verificador é feito o seguinte cálculo:

(n1*10)+(n2*9)+(n3*8)+(n4*7)+(n5*6)+(n6*5)+(n7*4)+(n8*3)+(n9*2)

Após somar todas as parcelas, dividi-se esse valor por 11.
Caso o resto desta divisão for 1 ou 0 então o primeiro dígito verificador é igual a zero.
Caso o resto desta divisão for maior ou igual a 2 então subtrai-se 11 do resto desta divisão e obtém-se então o primeiro dígito verificador.

Para encontrar qual é o segundo dígito verificador é feito o seguinte cálculo:
Observe que agora o primeiro dígito verificador também entra na conta.

(n1*11)+(n2*10)+(n3*9)+(n4*8)+(n5*7)+(n6*6)+(n7*5)+(n8*4)+(n9*3)+(n10*2)

Após somar todas as parcelas, dividi-se esse valor por 11.
Caso o resto desta divisão for 1 ou 0 então o segundo dígito verificador é igual a zero.
Caso o resto desta divisão for maior ou igual a 2 então subtrai-se 11 do resto desta divisão e obtém-se então o segundo dígito verificador.

A seguir segue uma função em PHP que retorna TRUE para CPF válidos e FALSE para CPF inválidos:
(Para aqueles que programam orientado a objetos basta colocá-la como método de sua classe)

function ValidaCPF ($partes){


$soma = ($partes[0]*10)+($partes[1]*9)+($partes[2]*8)+($partes[3]*7)+($partes[4]*6)+($partes[5]*5)+($partes[6]*4)+($partes[7]*3)+($partes[8]*2);


if ($soma%11<2)
   $D1 = 0;
   else
   $D1 = 11 -($soma%11);


$soma = ($partes[0]*11)+($partes[1]*10)+($partes[2]*9)+($partes[3]*8)+($partes[4]*7)+($partes[5]*6)+($partes[6]*5)+($partes[7]*4)+($partes[8]*3)+($partes[9]*2);


if ($soma%11<2)
   $D2 = 0;
   else
   $D2 = 11 -($soma%11);


//Após encontrar os dois dígitos verificadores ele testa se são iguais aos enviados pelo usuário
if ($D1==$partes[9] && $D2==$partes[10])
   return TRUE;
   else
   return FALSE;
}


Espero ter ajudado.....

sexta-feira, 15 de outubro de 2010

Comando alternativo ao MINUS

Ontem enfrentei um problema que talvez muitos iniciantes em linguagem SQL podem enfrentar....
Precisava de uma consulta que retornassem algumas colunas e que a chave primária da tabela não estivesse em uma tabela resultada de um SELECT...

Por exemplo:

Tabela clientes: `cliente_codigo`
Tabela produtos: `produto_codigo`
Tabela compras: `produto_codigo`,`cliente_codigo`

Sendo que a tabela `compras` mostra quem comprou algum produto...

O comando em questão seria caso fosse necessário achar aqueles clientes que ainda não efetuaram compras, ou seja, retornar todos os registros da tabela clientes que não estão presentes na tabela compras.
Usando o comando MINUS ficaria assim:

SELECT 'clientes'.'cliente_codigo'
FROM 'clientes'
MINUS
SELECT 'compras'.'cliente_codigo'
FROM 'compras';


Porém somento os clientes do Banco de Dados Oracle que tem essa exclusividades. Para aqueles (que como eu) que usam outro Banco de Dados será necessário usar o comando NOT IN:

SELECT 'clientes'.'cliente_codigo'
FROM 'clientes'
WHERE 'clientes'.'cliente_codigo' NOT IN
(
SELECT 'compras'.'cliente_codigo'
FROM 'compras'
);


Então para aqueles que encontrarem o comando MINUS em publicações, artigos, tutoriais e etc., fica o aviso que este comando é exclusivo do Oracle que uma alternativa é usar o comando NOT IN. Vale ressaltar ainda que há situações em que o NOT IN não consegue substituir o comando MINUS, mas isso já é assunto pra outra hora...

Vale ressaltar que a solução quem me trouxe foi o Prof. Fernando Prass....

Espero ter ajudado...
Abraço

Começando

É isso ai gurizada... Eu sou o Giordano Lima, sou acadêmico de Sistemas de Informação pela ULBRA/SM e vou tentar passar aqui algumas situações em que passo durante a rotina de desenvolvimento ou alguma experiência vista em aula....

O objetivo é ajudar aqueles que procuram por material e abrir espaço para aqueles que buscam o espaço para compartilhar informações...

O blog é totalmente aberto a postagens feitas por leitores, aqueles que tiverem alguma sugestão de postagem é só enviar um email para giordanol@gmail.com...

Espero que vocês gostem...
Um abraço....