I have a table that store payments. I need to merge the days a payment was made and when not.
So I will have something like:
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
I have this imperative solution, but is too slow for my case:
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()
I know I could create another table and store data with triggers. I wish to know if exist a efficient way to do this on the fly.
I also try generating a list of dates with the min/max values of the recaudo_deuda table, but then I don't see how build a result from this:
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$
You can do this with one single SQL statement, something like this:
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;