2016-08-03 17 views
0

支払いを保存するテーブルがあります。私は支払いが行われた日とそうでない日を合併する必要があります。postgresqlで日付間のギャップ行を生成する方法

だから私のようなものがあります:

DeudaId Date Value 
1 2016-01-01 $100 <- This come from a table 
1 2016-01-02 $0 <- This was calculated 
1 2016-01-03 $0 <- This was calculated 
1 2016-01-04 $100 <- This come from a table 

を私はこの不可欠解決策を持っていますが、私の場合のために遅すぎる:

CREATE OR REPLACE FUNCTION build_dates2() 
RETURNS TABLE (id INTEGER, cobrador_id INTEGER, fecha DATE) 
LANGUAGE plpgsql 
IMMUTABLE STRICT 
AS $function$DECLARE min_date DATE; 
DECLARE 
    r RECORD; 
    fecha RECORD; 
BEGIN 
    for r in (SELECT * FROM recaudo_deuda) LOOP 
     for fecha in (select toFecha(r.fecha) + s.a AS dates from generate_series(0, r.plazo) as s(a)) LOOP 
      return query VALUES (r.id, r.cobrador_id, fecha.dates); 
     END LOOP; 
    END LOOP; 
END 
$function$; 


SELECT * from build_dates2() 

私は私が別のテーブルとストアデータを作成することができます知っていますトリガー。私はその場でこれを行う効率的な方法が存在するかどうかを知りたい。

私はまたrecaudo_deudaテーブルの最小/最大値の日付のリストを生成しようとしたが、その後、私はこのことから、結果をビルドする方法を見ていない:

CREATE OR REPLACE FUNCTION public.build_dates() 
RETURNS TABLE(dates date) 
LANGUAGE plpgsql 
IMMUTABLE STRICT 
AS $function$ 
DECLARE min_date DATE; 
DECLARE dias INTEGER; 
BEGIN 
    SELECT min(fecha), extract(DAY from max(fecha) - min(fecha)) 
     from recaudo_deuda INTO min_date, dias; 

    RETURN QUERY select min_date + s.a AS dates from generate_series(0,dias) as s(a); 
END 
$function$ 

答えて

2

あなたは1でこれを行うことができます単一のSQLステートメント、このようなもの:

select d.deudaid, s.a as date, coalesce(d.value, 0) as value 
from (
    select min(fecha), max(fecha) 
    from recaudo_deuda 
) m (mi, mx) 
    cross join lateral generate_series(m.mi, m.mx, interval '1' day) as s(a) 
    left join recaudo_deuda d on d.fecha = s.a::date 
order by s.a; 
+0

しかし、私はしたいプロジェクトrecaudo_deuda場合はnullを取得します。この方法.id。私はそのレコードを日付に関連付ける必要があるので、recaudo_deuda.id、GenerateDate、NULLsを使って一連の行を取得します。 – mamcx

+1

@mamcx:そのために 'coalesce()'を使うことができます。 –

+0

値は問題ではなく、Idです。私はIdを保持する必要があります(存在するかどうか、またはその負債の支払いではない日付のビルドリスト)。質問のサンプルを参照してください。 – mamcx

0

ビットクレイジーソリューション。

簡単な例:

それは(私が列名を持つ正確であったことを確認していない)可能性があなたのケースに変換
with t(x) as (values(1),(2),(5),(10),(11)) 
select 
    x, 
    generate_series(x, coalesce(lead(x) over (order by x) - 1, x)) as x_gaps, 
    x = generate_series(x, coalesce(lead(x) over (order by x) - 1, x)) as x_real 
from t; 

select 
    deudaid, 
    generate_series(fecha, coalesce(lead(fecha) over (order by fecha) - '1d', fecha), '1d') as fecha, 
    (fecha = generate_series(fecha, coalesce(lead(fecha) over (order by fecha) - '1d', fecha), '1d'))::int * value as value 
from 
    recaudo_deuda; 
+0

'を選択して ' IDを選択すると、 fecha +(generate_series(0、60)|| '日'):: INTERVALとしてfecha から recaudo_deuda; 'しかし、実行が遅すぎます。ですから、deuda.idフィールドの60倍を繰り返す必要があります。 – mamcx

+0

@mamcxところで、充填されたギャップのない/テーブルの行数はいくつですか?私は、ほとんどの時間がデータ取得に費やされていると推測できます。そうであれば、サーバー側の代わりにクライアント側のギャップを埋める必要があります。 – Abelisto

関連する問題