Translate

sábado, 13 de dezembro de 2014

PostgreSql - Função LAG - Diferença de tempo para uma mesma coluna

Vamos apresentar 4 exemplos de como calcular a diferença de período para uma mesma coluna. Para isto vamos utilizar a função LAG do PostgreSql. Está função pertence ao grupo das Window Functions e funciona a partir do PostgreSQL 8.4.22

Caso tenha interesse, faça o download ou veja os scripts no github.


1º Exemplo

Um mercado que funciona 24 horas por dia quer calcular qual o intervalo que cada cliente aguarda em uma fila única. Neste exemplo, vamos utilizar a tabela "tb_venda", que podemos visualizar a seguir:

tb_venda
Solução

A tabela tb_venda possui as seguintes colunas:
  • cliente_id: a identificação de cada cliente;
  • data_hora: a data e a hora de inicio do atendimento para cada cliente;
Logo vamos ter que calcular a diferença de horário entre:
  • o 2º e 1º cliente;
  • o 3º e 2º cliente;
  • o 4º e 3º cliente;
  • e assim por diante;

Para exibir o intervalo que cada cliente aguarda executaremos a sentença abaixo:

SELECT
cliente_id,
data_hora, 
data_hora - LAG(data_hora) OVER (ORDER BY data_hora) AS tempo_espera
FROM tb_venda;

Após a execução da sentença teremos o seguinte resultado:


2º Exemplo

Uma loja de departamento que funciona das (08:00h às 23:00h) também quer calcular qual o intervalo que cada cliente aguarda em uma fila única. Será que poderíamos utilizar a mesma consulta do 1º exemplo em que o estabelecimento não fechava? Vamos tentar? Neste exemplo, vamos utilizar a tabela "tb_venda_depart", que podemos visualizar a seguir:




Para exibir o intervalo que cada cliente aguarda executaremos a sentença abaixo:

SELECT
cliente_id,
data_hora,
data_hora - LAG(data_hora) OVER (ORDER BY data_hora) AS tempo_espera
FROM tb_venda_depart;

Após a execução da sentença teremos o seguinte resultado:



Podemos verificar que a consulta está incorreta, pois o cliente 546, não ficou mais de 9h na fila, na verdade ele foi o primeiro cliente da fila do dia 27 de novembro e não teve que esperar na fila. Para corrigir a consulta vamos calcular a diferença para cada dia.

Para solucionar este problema vamos:

  • incluir na consulta o "PARTITION BY" para quebrar a consulta por data;
  • já que não temos uma coluna só com a data vamos truncar a coluna "data_hora" e utilizar somente a data, utilizando a função "DATE_TRUNC" do PostgreSql;   

SELECT
cliente_id,
data_hora,
data_hora - LAG(data_hora)
OVER (PARTITION BY(DATE_TRUNC('DAY', data_hora)) ORDER BY data_hora) AS tempo_espera
FROM tb_venda_depart;

Veja que o comando que foi adicionado está destacado em azul
Após a execução da sentença acima temos o resultado correto:



O cliente 546 foi o primeiro cliente do dia 27 de novembro, logo não precisou aguardar na fila.


3º Exemplo

Calcular a média de tempo de espera na fila para a loja de departamento. Para calcular a média também vamos utilizar a tabela "tb_venda_depart", conforme podemos visualizar abaixo:


tb_venda_depart
Solução

Vamos colocar a sentença anterior dentro de um comando "WITH" e vamos da o nome de "cliente_periodo" para este "WITH".
Quando fazemos isso é como se fosse criada uma tabela chamada cliente_periodo que contém três colunas:
cliente_id, data_hora, tempo_espera.

Depois vamos calcular a média para a coluna tempo_espera utilizando a função AVG.

Veja a sentença abaixo:


WITH cliente_periodo AS
(
SELECT
cliente_id,
data_hora,
data_hora - LAG(data_hora)
OVER (PARTITION BY(DATE_TRUNC('DAY', data_hora)) ORDER BY data_hora) AS tempo_espera
FROM tb_venda_depart
)
SELECT  AVG(tempo_espera) AS media_tempo_espera
FROM cliente_periodo;

Após a execução da sentença temos o seguinte resultado:



Logo, cada cliente espera em média, 4 minutos e 20 segundos e 5 milésimos.

4º Exemplo

Calcular a média de tempo de espera por dia (data). Para calcular a média também vamos utilizar a tabela "tb_venda_depart", conforme podemos visualizar abaixo:


tb_venda_depart
Solução


  • Vamos utilizar a sentença idêntica anterior, porém vamos adicionar o comando "GROUP BY" para que as médias sejam agrupadas por data.  
  • Como precisamos agrupar os dados por data e não temos uma coluna só com a data, vamos truncar a coluna data_hora e pegar só a data para o agrupamento, para isso vamos utilizar a função DATE_TRUNC do postgresql;
  • Vamos calcular a média para a coluna tempo_espera utilizando a função AVG.


Veja a sentença abaixo:

WITH cliente_periodo AS
(
   SELECT
   cliente_id,
   data_hora,
   data_hora - LAG(data_hora)
   OVER (PARTITION BY(DATE_TRUNC('DAY', data_hora)) ORDER BY data_hora) AS         tempo_espera
   FROM tb_venda_depart
)
SELECT DATE_TRUNC('DAY', data_hora), AVG(tempo_espera)
FROM cliente_periodo
GROUP BY DATE_TRUNC('DAY', data_hora);

Após a execução da sentença temos o seguinte resultado:




Veja que já temos a média de tempo de espera para cada dia, porém a data não está no formato dd/mm/yyyy.
Para que a data seja exibida neste formato, vamos utilizar a função TO_CHAR.

Veja a sentença abaixo utilizando TO_CHAR.


WITH cliente_periodo AS
(
SELECT
cliente_id,
data_hora,
data_hora - LAG(data_hora)
OVER (PARTITION BY(DATE_TRUNC('DAY', data_hora)) ORDER BY data_hora) AS tempo_espera
FROM tb_venda_depart
)
SELECT TO_CHAR(data_hora, 'DD/MM/YYYY'), AVG(tempo_espera)
FROM cliente_periodo
GROUP BY TO_CHAR(data_hora, 'DD/MM/YYYY');


Após a execução da sentença teremos o seguinte resultado:


Também podemos truncar a média de tempo de espera em hh:mm:ss, para não exibir os microssegundos depois do ponto vamos utilizar a função DATE_TRUNC para exibir a média até a unidade de segundos.

Veja a sentença abaixo:

WITH cliente_periodo AS
(
SELECT
cliente_id,
data_hora,
data_hora - LAG(data_hora)
OVER (PARTITION BY(DATE_TRUNC('DAY', data_hora)) ORDER BY data_hora) AS tempo_espera
FROM tb_venda_depart
)
SELECT TO_CHAR(data_hora, 'DD/MM/YYYY') AS DATA,
DATE_TRUNC('SECOND',AVG(tempo_espera)) AS media_tempo_espera
FROM cliente_periodo
GROUP BY TO_CHAR(data_hora, 'DD/MM/YYYY');

Após a execução da sentença teremos o seguinte resultado:



Artigos relacionados:


Deixe o seu comentário ou sugestão.
Gostou?  Siga no Google +  ou Facebook.

sábado, 29 de novembro de 2014

Postgresql - Função MIN

A função MIN retorna o valor mínimo (menor valor) de uma coluna. 
Serão descritos 3 exemplos de utilização desta função. 

Caso tenha interesse, faça o download ou veja os scripts no github.


SINTAXE
SELECT MIN(nome_da_coluna) FROM nome_da_tabela;

1º Exemplo
 
Neste exemplo, utilizaremos a tabela "tb_imoveis". Veja a imagem abaixo:

tb_imoveis
  

Cenário: qual o imóvel que possui o valor mais baixo?

Solução: o valor dos imóveis estão armazenados na coluna valor, logo devemos calcular o valor mais baixo a partir desta coluna.
Para calcularmos o valor mínimo, executamos a sentença abaixo:

SELECT MIN(valor) FROM tb_imoveis;

Após a execução, teremos o imóvel com o valor mais baixo. Conforme podemos visualizar na imagem a seguir:

O nome da coluna aparece como "min", mas vamos supor que precisamos que seja exibido "imovel_valor_minimo".
Podemos modificar o nome desta coluna, ou seja, criar um alias (apelido). Colocamos o alias depois do "AS
SELECT MIN(valorAS imovel_valor_minimo FROM tb_imoveis;

Após a execução, o nome da coluna será exibido como "imovel_valor_minimo".


2º Exemplo

Cenário: Uma equipe de três atletas treina uma série de corridas. Queremos saber qual foi o melhor treino para cada atleta, ou seja qual corrida levou menos tempo.
Neste exemplo, utilizaremos a tabela "tb_treino".

tb_treino

Solução: já que procuramos o menor tempo por atleta, vamos agrupar os atletas que estão armazenados na coluna "atleta_id". Para agrupar, utilizaremos o " GROUP BY".

Para calcularmos o menor tempo por atleta, executamos a sentença abaixo:

SELECT atleta_id, MIN(tempo) AS melhor_tempo
FROM tb_treino
GROUP BY atleta_id;

Após a execução, teremos o melhor tempo  para cada atleta. Conforme podemos visualizar na imagem abaixo:



Para ordenar a identificação dos atleta em ordem crescente, ou seja, do valor menor para o maior, deve-se usar "ORDER BY" seguido do nome da coluna, neste caso, a coluna 'atleta_idserá ordenada .
Para ordenar as identificações, utilizamos a sentença abaixo:

SELECT atleta_id, 
MIN(tempo) AS pior_tempo
FROM tb_treino
GROUP BY atleta_id
ORDER BY atleta_id;

Após a execução, teremos as identificações dos atletas em ordem crescente. Conforme podemos visualizar na imagem abaixo:




3º Exemplo

Cenário: Qual o atleta que obteve o melhor treino? Qual a data que o treino ocorreu?
Neste exemplo, utilizaremos a tabela "tb_treino".

tb_treino

Solução: também podemos utilizar a função "MIN" para filtrar um registro, desde que a função "MIN" pertença a uma subquery.

    Veja a subquery destacada, em azul, na sentença abaixo:

    SELECT 
    atleta_id,   
    data, 
    tempo AS melhor_tempo
    FROM tb_treino 
    WHERE tempo =
    (
        SELECT MIN(tempo)
        FROM tb_treino
    )

    Após a execução da sentença, teremos o resultado exibido na imagem abaixo:

    Observação:

    A função MIN não funciona no WHERE sem a subquery.

    WHERE tempo = MIN(tempo)

    Deixe o seu comentário ou sugestão.
    Gostou?  Siga no Google +  ou Facebook.

    domingo, 23 de novembro de 2014

    Postgresql - Funcão MAX

    A função MAX retorna o valor máximo (maior valor) de uma coluna. 
    Serão descritos 3 exemplos de utilização desta função. 

    Caso tenha interesse, faça o download ou veja os scripts no github.


    SINTAXE
    SELECT MAX(nome_da_coluna) FROM nome_da_tabela;

    1º Exemplo
     
    Neste exemplo, utilizaremos a tabela "tb_imoveis". Veja a imagem abaixo:

    tb_imoveis
      

    Cenário: qual o imóvel que possui o valor mais alto?

    Solução: o valor dos imóveis estão armazenados na coluna valor, logo devemos calcular o valor mais alto a partir desta coluna.
    Para calcularmos o valor máximo, executamos a sentença abaixo:

    SELECT MAX(valor) FROM tb_imoveis;

    Após a execução, teremos o imóvel com o valor mais alto. Conforme podemos visualizar na imagem abaixo:


    O nome da coluna aparece como "max", mas vamos supor que precisamos que seja exibido "imovel_valor_maximo".
    Podemos modificar o nome desta coluna, ou seja, criar um alias (apelido). Colocamos o alias depois do "AS
    SELECT MAX(valorAS imovel_valor_maximo FROM tb_imoveis;

    Após a execução, o nome da coluna será exibido como "imovel_valor_maximo".



    2º Exemplo

    Cenário: Uma equipe de três atletas treina uma série de corridas. Queremos saber qual foi o pior treino para cada atleta, ou seja qual corrida levou maior tempo.
    Neste exemplo, utilizaremos a tabela "tb_treino".

    tb_treino

    Solução: já que procuramos o maior tempo por atleta, vamos agrupar os atletas que estão armazenados na coluna "atleta_id". Para agrupar, utilizaremos o " GROUP BY".

    Para calcularmos o maior tempo por atleta, executamos a sentença abaixo:

    SELECT atleta_id, MAX(tempo) AS pior_tempo
    FROM tb_treino
    GROUP BY atleta_id;

    Após a execução, teremos o pior tempo  para cada atleta. Conforme podemos visualizar na imagem abaixo:




    Para ordenar a identificação dos atleta em ordem crescente, ou seja, do valor menor para o maior, deve-se usar "ORDER BY" seguido do nome da coluna, neste caso, a coluna 'atleta_idserá ordenada .
    Para ordenar as identificações, utilizamos a sentença abaixo:

    SELECT atleta_id, 
    MAX(tempo) AS pior_tempo
    FROM tb_treino
    GROUP BY atleta_id
    ORDER BY atleta_id;

    Após a execução, teremos as identificações dos atletas em ordem crescente. Conforme podemos visualizar na imagem abaixo:





    3º Exemplo

    Cenário: Qual o atleta que obteve o pior treino? Qual a data que o treino ocorreu?
    Neste exemplo, utilizaremos a tabela "tb_treino".




    Solução: também podemos utilizar a função "MAX" para filtrar um registro, desde que a função "MAX" pertença a uma subquery.

      Veja a subquery destacada, em azul, na sentença abaixo:

      SELECT 
      atleta_id,   
      data, 
      tempo AS pior_tempo
      FROM tb_treino 
      WHERE tempo =
      (
          SELECT MAX(tempo)
          FROM tb_treino
      )

      Após a execução da sentença, teremos o resultado exibido na imagem abaixo:


      Observação:

      A função MAX não funciona no WHERE sem a  subquery.

      WHERE tempo = MAX(tempo)

      Deixe o seu comentário ou sugestão.
      Gostou?  Siga no Google +  ou Facebook.

      sábado, 13 de setembro de 2014

      Postgresql - função LPAD

      Neste artigo, vamos mostrar 2 exemplos, da utilização da função LPAD.
       
      Utilizamos a função LPAD para completar uma string do lado esquerdo com determinado(s) caractere(s).

      O script dos exemplos, também estão no GitHub.

      SINTAXE

      LPAD (string, posicao_de_caracteres, 'caracter_para_preechimento')
      • string: sequëncia de caracteres;  
      • posicao_de_caracteres: indica até que posição a string será preenchida;
      • caracter_para_preechimento: caractere(s) utilizado(s) para o preenchimento, estes caracteres devem estar entre aspas;
      1º Exemplo

      Completar com o hifen (-) a esquerda dos nomes dos produtos até a 10ª posição.  
      Neste exemplo, vamos utilizar a coluna "nome_produto" tabela "tb_produto", exibida na imagem abaixo.
      tb_produto
      Solução

      SELECT
      nome_produto,
      LPAD (nome_produto,10, '-') AS nome_produto_com_hifen
      FROM tb_produto;

      Após a execução da sentença, teremos o seguinte resultado:

      Observações
      • lápis:        tem 5  caracteres e foi preenchida com 5 caracteres para completar as 10 posições;
      • caderno:  tem 7  caracteres e foi preenchida com 3 caracteres para completar as 10 posições;
      • borracha: tem 8 caracteres e foi preenchida com 2 caracteres para completar as 10 posições;
      • cartolina: tem 9 caracteres e foi preenchida com 1 caractere  para completar as  10 posições;
      No lugar do hífen (-), poderiamos utilizar qualquer outro caractere alfanumérico ou caractere especial.
      Por exemplo: uma ou mais letras, dígitos, espaços, asterisco entre outros.
        
      2º Exemplo

      Preencher com zeros "0" a esquerda, até a 5ª posição, os códigos dos produtos.
      Neste exemplo, vamos utilizar a coluna "codigo_produto" tabela "tb_produto", exibida na imagem abaixo.

      tb_produto

      Solução

      Como a função LPAD completa uma string, antes de utilizarmos a função LPAD, neste exemplo, devemos utilizar a função CAST para converter a coluna codigo_produto que é do tipo integer (número inteiro) para string (CHARACTER VARYING ou VARCHAR como é mais conhecido).

      SELECT
      LPAD (CAST(codigo_produto AS VARCHAR), 5, '0') AS codigo_produto, 
      nome_produto
      FROM tb_produto;

      Após a execução da sentença, teremos o seguinte resultado:


      Observações
      • O número   8426 tem   4 dígitos, e foi preenchido com 1 zero  para completar 5 dígitos;
      • O número     438 tem   3 dígitos, e foi preenchido com 2 zeros para completar 5 dígitos;  
      • O número       22 tem   2 dígitos, e foi preenchido com 3 zeros para completar 5 dígitos;
      • O número 16547 tem   5 dígitos, logo não foi preenchido com zeros, pois já contém 5 dígitos;
      Aprenda também a utilizar a função rpad:
      http://jquerydicas.blogspot.com.br/2017/07/postgresql-funcao-rpad.html

      Deixe o seu comentário ou sugestão.
      Gostou?  Siga no Google +  ou Facebook

      domingo, 7 de setembro de 2014

      Postgresql - Função replace

      Neste artigo, vamos mostrar 3 exemplos da utilização da função replace. O script dos exemplos também estão disponíveis no Git Hub

      Podemos utilizar a função replace para substituir:
      • uma ou mais palavras de uma de string;  
      • um ou mais caracteres de uma string; 
      SINTAXE
      REPLACE(COLUNA, DE, PARA)

      • COLUNA: coluna da tabela;
      • DE: o conteúdo que vamos substituir;
      • PARA: o novo conteúdo;
      1º Exemplo

      Substituir a abreviatura VW  pela palavra Wolkswagen.  
      Neste exemplo, vamos utilizar a coluna "modelo_veículo" da tabela "tb_veículo". Veja a tabela a seguir:

      tb_veiculo
      Solução:

      Para fazer a substituição utilizamos a sentença abaixo:

      SELECT
      modelo_veiculo,
      REPLACE(
      modelo_veiculo, '
      VW', 'Wolkswagen') AS substituicao  
      FROM tb_veiculo


      Após a execução da sentença acima teremos o seguinte resultado:




      2º Exemplo

      Substituir:
      • a abreviatura VW  pela palavra Wolkswagen;
      • a abreviatura GM  pela palavra General Motors; 
      Neste exemplo, também vamos utilizar a coluna "modelo_veículo" da tabela "tb_veículo". 

      tb_veiculo
      Solução:

      Para fazer a substituição, além da função, REPLACE vamos utilizar a condição "CASE  WHEN" para substituir a sigla de acordo com a situação. 

      Obs: Caso tenha interesse, veja o artigo: PostgreSql - Exemplo CASE WHEN

      Veja a sentença abaixo:

      SELECT
      modelo_veiculo,
      CASE
          WHEN (modelo_veiculo LIKE '%
      VW%') 
              THEN REPLACE(modelo_veiculo, 'VW', 'Wolkswagen')
         
      WHEN (modelo_veiculo LIKE '%GM%') 
             THEN REPLACE(modelo_veiculo, 'GM', 'General Motors')   
      END  AS substituicao
      FROM tb_veiculo


      Após a execução da sentença acima teremos o seguinte resultado:


      3 º Exemplo

      Substituir o caractere "o" pelo caractere "a" de uma mensagem. Neste exemplo, vamos utilizar a coluna "mensagem" da tabela "tb_mensagem". Veja a tabela a seguir:

      tb_mensagem

      Para exibir a substituição utilizamos a sentença abaixo:

      SELECT
      data,
      mensagem, 
      REPLACE(
      mensagem, 'o', 'a') AS nova_mensagem
      FROM tb_mensagem;


      Após a execução da sentença acima teremos o seguinte resultado:


      Deixe o seu comentário ou sugestão sobre este artigo.
      Gostou? Curta a nossa página.