Reputation: 353
I have a table with many rows so when I make this query:
SELECT
date_trunc('hour', fecha) AS momento
,(extract(minute FROM fecha)::int / 5) AS min
,count(fecha) AS cuenta
FROM table1
WHERE fk_id_busqueda=$id_busqueda
GROUP BY 1, 2
ORDER BY 1, 2;
It takes a lot of time. One solution that I am thinking is make a postgres function where I can order the data by date and then sum one everytime momento of the previous row is the same than the actual one with a loop. And when is different then reset the value and pass to the Next row. The idea is that the function recives id_busqueda (int).
The output should be like this:
2013-01-20 00:00:00 | 0 | 16
2013-01-20 00:00:00 | 1 | 30
2013-01-20 00:00:00 | 2 | 27
2013-01-20 00:00:00 | 3 | 30
2013-01-20 00:00:00 | 4 | 33
2013-01-20 00:00:00 | 5 | 21
2013-01-20 00:00:00 | 6 | 27
2013-01-20 00:00:00 | 7 | 27
2013-01-20 00:00:00 | 8 | 19
2013-01-20 00:00:00 | 9 | 13
2013-01-20 00:00:00 | 10 | 17
2013-01-20 00:00:00 | 11 | 24
2013-01-20 01:00:00 | 0 | 12
2013-01-20 01:00:00 | 1 | 15
2013-01-20 01:00:00 | 2 | 25
2013-01-20 01:00:00 | 3 | 19
2013-01-20 01:00:00 | 4 | 10
2013-01-20 01:00:00 | 5 | 12
2013-01-20 01:00:00 | 6 | 13
Upvotes: 3
Views: 1107
Reputation: 125304
In addition to the index creation on the fk_id_busqueda column this should shave a bit more from the execution time:
SELECT
date_trunc('minute', fecha) -
(extract(minute from fecha)::integer % 5) * interval '1 minute' as momento
,count(fecha) AS cuenta
FROM table1
WHERE fk_id_busqueda=$id_busqueda
GROUP BY 1
ORDER BY 1
Upvotes: 2
Reputation: 121654
I hope this function do the task.
create or replace function myfunc(id_busqueda integer)
returns table (momento timestamp, min int, cuenta int)
language plpgsql as $$
declare
t record;
momento timestamp;
imomento timestamp;
mins integer;
imins integer;
was boolean;
begin
was := false;
cuenta := 1;
for t in
select fecha
from table1
where fk_id_busqueda = id_busqueda
order by fecha
loop
momento := date_trunc('hour', t.fecha);
mins := extract(minute FROM t.fecha)::int / 5;
if imins = mins and imomento = momento then
cuenta := cuenta+ 1;
else
if was then
return query select imomento, imins, cuenta;
end if;
cuenta := 1;
imins := mins;
imomento := momento;
was := true;
end if;
end loop;
if was then
return query select imomento, imins, cuenta;
end if;
end; $$;
Upvotes: 1