Separar linhas em colunas postgresql
Bom dia amigos,
estou com dificuldades no postgre SQL em separar linhas em colunas, por exemplo:
Tenho os seguintes dados:
Data | Máquina | Qtd
01/07/2014 | serra 1 | 12
01/07/2014 | serra 2 | 18
02/07/2014 | serra 1 | 14
02/07/2014 | serra 2 | 15
Quero apresentar da seguinte forma:
Máquina | 01/07/2014 | 02/07/2014
serra 1 | 12 | 14
serra 2 | 18 | 15
e assim sucessivamente conforme for abastecendo o banco com mais datas...
Grato.
estou com dificuldades no postgre SQL em separar linhas em colunas, por exemplo:
Tenho os seguintes dados:
Data | Máquina | Qtd
01/07/2014 | serra 1 | 12
01/07/2014 | serra 2 | 18
02/07/2014 | serra 1 | 14
02/07/2014 | serra 2 | 15
Quero apresentar da seguinte forma:
Máquina | 01/07/2014 | 02/07/2014
serra 1 | 12 | 14
serra 2 | 18 | 15
e assim sucessivamente conforme for abastecendo o banco com mais datas...
Grato.
Renan Maia
Curtidas 0
Melhor post
Ronaldo Lanhellas
07/07/2014
Bom, criei uma função com base nos dados que você me passou. A forma que pensei foi mostrar através do RAISE NOTICE a formatação que você deseja, mas fique a vontade para mudar se precisar.
Testei e a saída foi essa:
CREATE OR REPLACE FUNCTION public.func_dados_serra (
)
RETURNS void AS
$body$
DECLARE
r RECORD;
p RECORD;
q RECORD;
qtd_aux integer;
cabecalho text;
linha text;
BEGIN
cabecalho = 'MAQUINA';
FOR r IN SELECT data FROM dados_serra GROUP BY data ORDER BY data ASC
LOOP
cabecalho = cabecalho || ' | ' || r.data;
END LOOP;
RAISE NOTICE '%',cabecalho;
FOR p IN SELECT maquina FROM dados_serra GROUP BY maquina
LOOP
linha = p.maquina;
FOR q IN SELECT qtd FROM dados_serra WHERE maquina = p.maquina ORDER BY data ASC
LOOP
linha = linha || ' | ' || q.qtd;
END LOOP;
RAISE NOTICE '%',linha;
END LOOP;
END;
$body$
LANGUAGE 'plpgsql'
VOLATILE
CALLED ON NULL INPUT
SECURITY INVOKER
COST 100;
Testei e a saída foi essa:
NOTICE: MAQUINA | 2014-07-01 | 2014-07-02 NOTICE: serra 1 | 12 | 14 NOTICE: serra 2 | 18 | 15 Total query runtime: 33 ms. 1 row retrieved.
GOSTEI 1
Mais Respostas
Ronaldo Lanhellas
07/07/2014
No seu caso notei que as colunas são dinâmicas, pois podem existir diversas datas e você não tem como saber quantas são. A melhor solução seria criar uma função que montasse o seu SQL de forma dinâmica.
GOSTEI 0
Renan Maia
07/07/2014
Obrigado pela resposta Ronaldo,
Porém sou novo na área de programação etc... poderia me dar um exemplo de como fazer isso?
Mais uma vez obrigado.
Porém sou novo na área de programação etc... poderia me dar um exemplo de como fazer isso?
Mais uma vez obrigado.
GOSTEI 0
Fabiano Carvalho
07/07/2014
Pesquise por pivot ou crosstab, se voce informar as datas manualmente irá fazer o que voce deseja, mas é aconselhado a fazer a função como foi indicado.
Não posso te ajudar tanto pois não trabalho com postgre, mas pela pesquisa rápida encontrei algumas soluções.
Não posso te ajudar tanto pois não trabalho com postgre, mas pela pesquisa rápida encontrei algumas soluções.
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Vou preparar um exemplo e já lhe repasso.
GOSTEI 0
Renan Maia
07/07/2014
Ótimo Ronaldo, muito obrigado pela ajuda, ainda não testei mas creio que irá funcionar.
Fabiano, obrigado pela dica.
Att
Renan.
Fabiano, obrigado pela dica.
Att
Renan.
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Bom, funcionar funciona, partindo da estrutura de tabela que você passou no início do post, só não sei se é exatamente o que você precisa. De qualquer forma, já é um começo e você pode adaptar para sua necessidade.
GOSTEI 0
Renan Maia
07/07/2014
Fiz todos os teste agora a tarde, porem achei a solução para meu problema, o FastReport possui o objeto Cross Tab, que pode ser ordenado de forma visual a tabela.
Portanto, se alguém tiver o mesmo problema, o fast possui uma solução fácil.
Portanto, se alguém tiver o mesmo problema, o fast possui uma solução fácil.
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Bom, de fato usar uma IDE para construção de relatório simplifica tudo, mas como você não exemplificou para que precisava disso, não tinha como opinar.
GOSTEI 0
Renan Maia
07/07/2014
Bom, eu precisava extrair do banco de dados e apresentar de alguma forma, apos quebrar a cabeça a tarde toda é que veio a ideia de montar um gerador de relatórios pra simplificar tudo :).
Mas agora estou com um novo problema, tenho a seguinte linha de comando na Query/postgres, que seleciona a tabela de tempo parado de cada máquina e apresenta numa query...
select pa.ds_parada, sum(ap.qtd_minutoparado) as minutos
from apontador ap
inner join paradas pa on pa.seq = ap.cd_parada
where ap.cd_horas = 11 and ap.dt_apontador between '01/07/2014' and '09/07/2014'
group by pa.ds_parada
.... que me traz os seguintes dados no postgres...
"RETRABALHO";250
"TROCA DE FERRAMENTAS/SETUP";2040
"FALTA DE PROGRAMACAO";75
"FALHA MECANICA";135
"CAFÉ/ALIMENTAÇÃO";90
"FALHA ELETRICA";1310
"FALTA DE EXAUSTAO";175
"FALTA DE MATERIA PRIMA";1100
"REUNIAO/TREINAMENTO";60
"FALTA DE AR COMPRIMIDO";135
"FALTA DE COLABORADOR";180
"FALTA DE EMPILHADEIRA";60
...existe aluma função especifica no POSTGRES para converter os valores que estão em minutos para horas, pois só dividir por exemplo os 250 minutos da primeira linha por 60 não resolve o problema.
Grato.
Mas agora estou com um novo problema, tenho a seguinte linha de comando na Query/postgres, que seleciona a tabela de tempo parado de cada máquina e apresenta numa query...
select pa.ds_parada, sum(ap.qtd_minutoparado) as minutos
from apontador ap
inner join paradas pa on pa.seq = ap.cd_parada
where ap.cd_horas = 11 and ap.dt_apontador between '01/07/2014' and '09/07/2014'
group by pa.ds_parada
.... que me traz os seguintes dados no postgres...
"RETRABALHO";250
"TROCA DE FERRAMENTAS/SETUP";2040
"FALTA DE PROGRAMACAO";75
"FALHA MECANICA";135
"CAFÉ/ALIMENTAÇÃO";90
"FALHA ELETRICA";1310
"FALTA DE EXAUSTAO";175
"FALTA DE MATERIA PRIMA";1100
"REUNIAO/TREINAMENTO";60
"FALTA DE AR COMPRIMIDO";135
"FALTA DE COLABORADOR";180
"FALTA DE EMPILHADEIRA";60
...existe aluma função especifica no POSTGRES para converter os valores que estão em minutos para horas, pois só dividir por exemplo os 250 minutos da primeira linha por 60 não resolve o problema.
Grato.
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Porque não resolve o problema ? Qual o tipo de dado da sua coluna ?
Pois se fizer isso:
Verá que o resultado = 4, minutos.
Pois se fizer isso:
SELECT 250/4;
Verá que o resultado = 4, minutos.
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Porque não resolve o problema ? Qual o tipo de dado da sua coluna ?
Pois se fizer isso:
Verá que o resultado = 4, minutos.
Pois se fizer isso:
SELECT 250/4;
Verá que o resultado = 4, minutos.
Desculpe, corrigindo o codigo acima:
SELECT 250/60;
GOSTEI 0
Renan Maia
07/07/2014
A coluna minutos é do tipo integer, logo se eu dividir 250 por 60 = 4,16 horas, até ai tudo bem, sei que são 4 horas e pra eu saber o valor do ,16 é tenho que multiplicar novamente por 60 pra saber quantos minutos representam 0,16. O problema é que não sei como pegar somente o ,16 e multiplica por 60.
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Tente assim:
select (250/60) as hora, (250.0/60.0) - (250/60) as minutos;
GOSTEI 0
Renan Maia
07/07/2014
Ronaldo, deu certo assim. Retornou 4 horas, 10 minutos.
#Código
select (250/60) as hora, ((250.0/60.0) - (250/60))*60 as minutos;
#Código
select (250/60) as hora, ((250.0/60.0) - (250/60))*60 as minutos;
GOSTEI 0
Ronaldo Lanhellas
07/07/2014
Ótimo, que bom que deu certo.
GOSTEI 0
Renan Maia
07/07/2014
Portanto, se alguém precisar do codigo que converta minutos em horas (horas serão no formato string) segue abaixo...
retornou o seguinte valor...
"TROCA DE FERRAMENTAS/SETUP31:0";1860
"FALHA ELETRICA";"21:49";1310
"FALTA DE MATERIA PRIMA";"18:19";1100
"RETRABALHO";"4:10";250
"FALTA DE EXAUSTAO";"2:55";175
"FALTA DE AR COMPRIMIDO";"2:15";135
"FALHA MECANICA";"2:15";135
"FALTA DE COLABORADOR";"2:0";120
"CAFÉ/ALIMENTAÇÃO";"1:30";90
"REUNIAO/TREINAMENTO";"1:0";60
"FALTA DE EMPILHADEIRA";"1:0";60
"FALTA DE PROGRAMACAO";"0:45";45
select pa.ds_parada, coalesce(cast( (sum(ap.qtd_minutoparado)/60) as varchar),'') || (':') ||
coalesce(cast(trunc(((sum(ap.qtd_minutoparado)/60.0 - (sum(ap.qtd_minutoparado)/60))*60)) as varchar), '') as horas, sum(ap.qtd_minutoparado) as minutos
from apontador ap
inner join paradas pa on pa.seq = ap.cd_parada
where ap.cd_horas = 11 and ap.dt_apontador between '01/07/2014' and '08/07/2014'
group by pa.ds_parada
order by minutos desc
retornou o seguinte valor...
"TROCA DE FERRAMENTAS/SETUP31:0";1860
"FALHA ELETRICA";"21:49";1310
"FALTA DE MATERIA PRIMA";"18:19";1100
"RETRABALHO";"4:10";250
"FALTA DE EXAUSTAO";"2:55";175
"FALTA DE AR COMPRIMIDO";"2:15";135
"FALHA MECANICA";"2:15";135
"FALTA DE COLABORADOR";"2:0";120
"CAFÉ/ALIMENTAÇÃO";"1:30";90
"REUNIAO/TREINAMENTO";"1:0";60
"FALTA DE EMPILHADEIRA";"1:0";60
"FALTA DE PROGRAMACAO";"0:45";45
GOSTEI 0
Renan Maia
07/07/2014
Complementando, primeira coluna é a descrição (varchar), segunda coluna é as horas (varchar) e a terceira coluna são os minutos (int);
Abraço.
Abraço.
GOSTEI 0