2015-02-02 12:22 GMT-02:00 Marco Aurelio <[email protected]>:

> select row_number() over() as id,  dt_vencto, vl_duplica from
> receber_duplica
> left outer join notas using(nota_id)
> where nota_id = 114
> order by dt_vencto
>
>
Primeiro, evite usar row_number com OVER sem ORDER BY, apesar do resultado
ser o esperado em versões atuais (sempre será), pela definição poderia ser
inconsistente, então no seu caso use simplesmente o mesmo ORDER BY da
consulta:

    SELECT row_number() OVER(ORDER BY dt_vencto) AS id, ...
    ...
    ORDER BY dt_vencto;


id;dt_vencto;vl_duplica
> 1;"2015-02-28";0.70
> 2;"2015-03-31";0.70
> 3;"2015-04-30";0.70
> 4;"2015-05-31";0.70
> 5;"2015-06-30";0.70
> 6;"2015-07-31";0.70
> 7;"2015-08-31";0.70
> 8;"2015-09-30";0.70
> 9;"2015-10-31";0.70
> 10;"2015-11-30";0.70
>
>  este número de linhas obviamente é variavel.
>
> Gostaria que me retornasse assim:
>
> dt_vencto1;vl_duplica1;  dt_vencto2;vl_duplica2;dt_vencto3;vl_duplica3
> 1;2015-02-28;0,70;         2;2015-03-31;0,70        3;2015-04-30;0,70
> 4;2015-05;30;0,70          etc
>
> quebrando em 3 conjunto de colunas;
>
> sei que dá pra fazer com TEMPORARY TABLES
>
> DROP TABLE IF EXISTS temporary_duplica;
> CREATE TEMPORARY TABLE temporary_duplica as (
> select row_number() over() as id,  dt_vencto, vl_duplica from
> receber_duplica
> left outer join notas using(nota_id)
> where nota_id = 114
> order by dt_vencto
> );
>
>
> select * from (select * from temporary_duplica where id%4=1) as a
> left outer join(select * from temporary_duplica where id%4=2) as b on a.id+1
> = b.id
> left outer join(select * from temporary_duplica where id%4=3) as c on a.id+2
> = c.id
> left outer join(select * from temporary_duplica where id%4=0) as d on a.id+3
> = d.id
>
> mas neste caso como uso jasper ele não reconhece estas TEMPORARY TABLEs.
>
>
Nem sei o porquê você decidiu usar tabelas temporárias, até no seu exemplo
poderia simplesmente usar Common Table Expression (CTE) com a cláusula WITH:

    WITH temporary_duplica AS (
        <consulta original>
    )
    SELECT * FROM ...;


> E sei que daria pra fazer tb, repetindo a query várias vezes, mas gostaria
> de saber se tem como com windows functions obter estes resultados.
>

Bom, agora das melhores soluções eu vejo o uso da WINDOW FUNCTION lead ou
usando a função crosstab da extensão tablefunc [1].

A função "lead" o valor da próxima linha, o da linha após "N" valores onde
N é o segundo parâmetro da função. Ficaria mais ou menos (não testado)
assim:

    SELECT * FROM (
        SELECT row_number() OVER w AS id,
            dt_vencto AS dt_vencto1, vl_duplica AS vl_duplica1,
            lead(dt_vencto, 1) OVER w AS dt_vencto2, lead(vl_duplica, 1)
OVER w AS vl_duplica2,
            lead(dt_vencto, 2) OVER w AS dt_vencto3, lead(vl_duplica, 2)
OVER w AS vl_duplica3,
            lead(dt_vencto, 3) OVER w AS dt_vencto4, lead(vl_duplica, 3)
OVER w AS vl_duplica4
        FROM receber_duplica
        LEFT OUTER JOIN notas USING(nota_id)
        WHERE nota_id = 114
        WINDOW w AS (ORDER BY dt_vencto)
        ORDER BY dt_vencto
    ) t
    WHERE t.id % 4 = 0
    ORDER BY dt_vencto1;

A ideia é usar a "lead" para em cada linha buscar o valor da linha, e das 3
próximas. Depois usar o filtro `t.id % 4 = 0` para pegar remover as
duplicatas que serão geradas (execute só a consulta interna para conferir).

Mais uma dica, como boa prática eu recomendaria você a usar apelidos
("alias") nas consultas.

Atenciosamente,
-- 
Matheus de Oliveira
Analista de Banco de Dados
Dextra Sistemas - MPS.Br nível F!
www.dextra.com.br/postgres
_______________________________________________
pgbr-geral mailing list
[email protected]
https://listas.postgresql.org.br/cgi-bin/mailman/listinfo/pgbr-geral

Responder a