Vinzenz Mai: performante Verteilungsstatistik

Beitrag lesen

Hallo Ingrid,

wie ich selbst einmal schrieb, ist es keine gute Idee, Namen nachträglich zu ändern. Es ist schön zu sehen, dass meine Tabelle "ergebnis" bei meinen Tests "temptest" hieß ...

Weiterhin habe ich die Intervallbreite einer Variablen zugewiesen, damit diese sich leichter anpassen lässt. Derzeit ist zu bedenken, dass die Intervallbreite auch im View auftaucht. Wenn View und Funktion durch eine weitere Funktion erstellt würden, könnte man die Intervallbreite über einen Übergabeparameter steuern, das wäre eine erste Verbesserung.

Im nächsten Schritt wird eine Funktion erstellt, die die Ergebnistabelle mit den kumulierten Daten füllt - und nicht besetzte Intervalle einfügt.

CREATE FUNCTION aktualisiere_ergebnis() RETURNS bigint AS $$  
DECLARE  
    schritt   bigint;  -- Schrittweite  
    beginn    bigint;  -- Startwert der Intervalle  
    gesamt    bigint;  -- Gesamtzahl der Datensätze  
    aktuell   bigint;  -- aktuelles Intervall  
    k_summe   bigint;  -- kumulierte Summe  
    datensatz RECORD;  -- aktueller Datensatz  
BEGIN  
    -- Schrittweite setzen  
    schritt := 10;  
    -- Leere die Ergebnistabelle  
    TRUNCATE ergebnis;  
    -- Ermittle den Startwert  
    beginn  := schritt * MIN(cast(CEIL(cast(innerwidth as real)/schritt) as int)) FROM test;  
    -- Ermittle die Gesamtzahl der Datensätze  
    gesamt  := COUNT(*) FROM test;  
    -- Setze die Startwerte  
    aktuell := beginn;  
    k_summe := 0;  
  
    -- Durchlaufe alle Datensätze  
    FOR datensatz IN SELECT abschnitt, summe FROM gruppierung ORDER BY abschnitt LOOP  
        -- Falls Intervalle nicht besetzt sind, müssen sie eingetragen werden  
        WHILE cast(aktuell as int) < cast(datensatz.abschnitt as int) LOOP  
            INSERT INTO ergebnis (abschnitt, summe, total)  
                VALUES (aktuell, k_summe, gesamt);  
            -- nächstes Intervall  
            aktuell := aktuell + schritt;  
        END LOOP;  
        -- verarbeite aktuellen Datensatz  
        -- Berechne die kumulierte Summe neu  
        k_summe := k_summe + datensatz.summe;  
  
        -- Schreibe den Datensatz weg  
        INSERT INTO ergebnis (abschnitt, wert, summe, total) VALUES (datensatz.abschnitt, datensatz.summe, k_summe, gesamt);  
        -- setze das nächste Intervall (sonst gibt es Doppeleinträge)  
        aktuell := cast(datensatz.abschnitt as int) + schritt;  
        -- Am Ende ist grundsätzlich ein besetztes Intervall :-)  
    END LOOP;  
  
    RETURN 1;  
END;  
$$ LANGUAGE plpgsql;

Freundliche Grüße

Vinzenz