/*
Obrigado Osvaldo e JotaComm, ufa! como simplificou a minha vida, vejam
como fazia antes com store function  e de longe não era melhor solução
comparada com esta, desde já agradeço se  alguém quiser postar algum
exemplo com  window function
Veja como fazia com store function, como era sofrivel a minha vida :)
*/

--type do store function
DROP TYPE IF EXISTS public.tp_transform_rows_into_column CASCADE;
CREATE TYPE public.tp_transform_rows_into_column AS
(
          c1 TEXT
        , c2 TEXT
        , c3 TEXT
        , c4 TEXT
        
);

--store function
DROP FUNCTION IF EXISTS sf_transform_rows_into_column (sqlx TEXT);
CREATE OR REPLACE FUNCTION sf_transform_rows_into_column (sqlx TEXT)
     RETURNS SETOF public.tp_transform_rows_into_column AS

$$
DECLARE
row1                public.tp_transform_rows_into_column;
row2                public.tp_transform_rows_into_column;
row3                public.tp_transform_rows_into_column;
ds_comando          TEXT;
controle            TEXT;
n_col_transf_rx     TEXT;
n_contador          FLOAT;

BEGIN

     IF (sqlx IS NULL) THEN
          RAISE EXCEPTION 'QUERY VALORES NULOS!'; -- caso o parametro venha nulo
     END IF;

     n_col_transf_rx     := '';
     ds_comando          := 'SELECT * FROM ( ' || sqlx || ' ) AS foo
ORDER BY 1 ASC, 3 ASC';
     controle            := '';
     n_contador          := 0;

     FOR row1 IN EXECUTE
          ds_comando

          LOOP

          IF row1.c1 <> controle THEN

               n_col_transf_rx     := '';
               row2.c1             := row1.c1;
               row2.c2             := row1.c2;
               row2.c3             := row1.c3;
               row2.c4             := row1.c4 || ';';
               n_col_transf_rx     := row1.c4 || ';';

          ELSIF  row1.c1 = controle  THEN

               n_col_transf_rx     := n_col_transf_rx || row1.c4 ||
';';
               row2.c4             := n_col_transf_rx;

          END IF;

          IF row2.c1 <> row3.c1 THEN

               RETURN NEXT row3;

          END IF;

          controle            := row1.c1;
          row3                := row2;
          n_contador          := n_contador + 1;

          RAISE NOTICE 'Processando tupla... %', n_contador;

     END LOOP;

     RETURN NEXT row2;

     RAISE NOTICE 'Processo concluido com sucesso!!!';

     RETURN;

EXCEPTION WHEN QUERY_CANCELED THEN
     RAISE NOTICE 'Processo cancelado, ROLLBACK EFETUADO!!!';

     RETURN;
        
END;
$$
LANGUAGE 'plpgsql'
;
-- depois para execução
--como havia anteriormente feito
     SELECT *
       FROM sf_transform_rows_into_column
                                        ($$
                                             SELECT cpf
                                                  , nome
                                                  , 1 AS status
                                                  , matricula
                                               FROM cadastro_teste ORDER BY cpf
                                        $$);

-- com a versão sugerida por Osvaldo na versão PostgreSQL 8.3, ficou assim:
-- para versao Postgres 8.3
CREATE AGGREGATE array_accum (anyelement)
(
    sfunc = array_append,
    stype = anyarray,
    initcond = '{}'
);

SELECT cpf, nome, array_accum(matricula) FROM cadastro_teste GROUP BY
cpf, nome;  -- apenas na versao do Postgres 8.3

--Muito simples ! Show!
--Valeu !
/*
Emerson Hermann
DBA
*/

Em 29 de outubro de 2010 08:58, JotaComm <[email protected]> escreveu:
> Opa,
>
> 2010/10/28 Emerson Hermann <[email protected]>
>>
>> /*
>> Estrutura apenas para exemplo
>> */
>> --DROP TABLE IF EXISTS cadastro_teste;
>> CREATE TEMP TABLE cadastro_teste
>> (
>>       cpf  VARCHAR(11)
>>     , nome VARCHAR(21)
>>     , matricula VARCHAR(7)
>>
>> );
>>
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES ('Maria
>> Madalena','72034054401','2010011');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES
>> ('Jonas','12034054408','2010032');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES ('Maria
>> Madalena','72034054401','2010051');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES ('Maria
>> Madalena','72034054401','2010071');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES
>> ('Jonas','12034054408','2010559');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES
>> ('Marcos','42034054403','2010033');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES
>> ('Marcos','42034054403','2010154');
>> INSERT INTO cadastro_teste (nome,cpf,matricula) VALUES
>> ('Joao','53034054403','2010004');
>>
>>
>> SELECT * FROM cadastro_teste ORDER BY cpf;
>> /*
>>
>> cpf        |nome          |matricula
>> 12034054408|Jonas         |2010559
>> 12034054408|Jonas         |2010032
>> 42034054403|Marcos        |2010154
>> 42034054403|Marcos        |2010033
>> 53034054403|Joao          |2010004
>> 72034054401|Maria Madalena|2010071
>> 72034054401|Maria Madalena|2010051
>> 72034054401|Maria Madalena|2010011
>>
>> */
>>
>> -- Existe a possibilidade de agrupar esses dados da forma abaixo
>> (concatenando a matricula) sem uso de store function? Utilizo
>> PostgreSQL 8.3.
>> -- Se existe, como seria, com window function  ?
>
> Sim, com o uso de Window Functions, porém disponível apenas para a versão
> 8.4
>>
>>
>> /*
>> cpf        |nome          |matricula
>> 12034054408|Jonas         |2010032;2010559;
>> 42034054403|Marcos        |2010033;2010154;
>> 53034054403|Joao          |2010004;
>> 72034054401|Maria Madalena|2010011;2010051;2010071;
>> */
>
> O restante o meu colega Osvaldo já deu a dica.
>>
>> _______________________________________________
>> pgbr-geral mailing list
>> [email protected]
>> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
>
> []s
> --
> JotaComm
> http://jotacomm.wordpress.com
>
> _______________________________________________
> pgbr-geral mailing list
> [email protected]
> https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral
>
>
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a