Frage

Ich bin auf der Suche Kumulative Frequenzdaten aus unserer Datenbank zu erhalten. Ich habe eine einfache temporäre Tabelle mit all einzigartigen Status-Update zählt geschaffen, dass wir gesehen haben, und die Anzahl der Nutzer, die diese Menge an Status-Updates haben.

     Table "pg_temp_4.statuses_count_tmp"
     Column     |  Type   | Modifiers 
----------------+---------+-----------
 statuses_count | integer | 
 frequency      | bigint  | 
Indexes:
    "statuses_count_idx" UNIQUE, btree (statuses_count)

Meine aktuelle Abfrage ist:

select statuses_count, frequency/(select * from total_statuses)::float, (select sum(frequency)/(select * from total_statuses)::float AS percentage from statuses_count_tmp WHERE statuses_count <= SCT.statuses_count) AS cumulative_percent  FROM statuses_count_tmp AS SCT ORDER BY statuses_count DESC;

Aber das dauert eine ganze Weile, und die Anzahl der Anfragen wächst ziemlich schnell. So mit den ~ 50.000 Zeilen Ich habe, ich suche bei 50k faktorielles Zeilen gelesen werden. Ich hoffe, Theres eine bessere Lösung, dass ich nicht durch von noch hier sitzen die Abfrage grind beobachten weg.

Hoffnung, etwas zu bekommen:

0       0.26975161      0.26975161
1       0.15306534      0.42281695
2       0.05513516      0.47795211
3       0.03050646      0.50845857
4       0.02064444      0.52910301
War es hilfreich?

Lösung

Sollte mit Windowing-Funktionen auflösbar sein, vorausgesetzt, Sie PostgreSQL 8.4 oder höher. Ich vermute, dass total_statuses eine Ansicht oder temporäre Tabelle entlang der Linien von select sum(frequency) from statuses_count_tmp? Ich schrieb es als hier CTE was machen sollte das Ergebnis nur einmal für die Dauer der Anweisung berechnen:

with total_statuses as (select sum(frequency) from statuses_count_tmp)
select statuses_count,
       frequency / (select * from total_statuses) as frequency,
       sum(frequency) over(order by statuses_count)
           / (select * from total_statuses) as cumulative_frequency
from statuses_count_tmp

Ohne 8.4 Fenster Funktionen die beste Wahl ist einfach die Daten zu verarbeiten iterativ:

create type cumulative_sum_type as ( statuses_count int, frequency numeric, cumulative_frequency numeric );
create or replace function cumulative_sum() returns setof cumulative_sum_type strict stable language plpgsql as $$
declare
  running_total bigint := 0;
  total bigint;
  data_in record;
  data_out cumulative_sum_type;
begin
  select sum(frequency) into total from statuses_count_tmp;
  for data_in in select statuses_count, frequency from statuses_count_tmp order by statuses_count
  loop
    data_out.statuses_count := data_in.statuses_count;
    running_total := running_total + data_in.frequency;
    data_out.frequency = data_in.frequency::numeric / total;
    data_out.cumulative_frequency = running_total::numeric / total;
    return next data_out;
  end loop;
end;
$$;
select * from cumulative_sum();
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top