2017-01-26 3 views
1

I Greenplum DB bin mit und ich mag Median in einem Fenster berechnen, so etwas wie:Benutzerdefinierte Greenplum Aggregatfunktion mit Fenstern

SELECT avg(var1) OVER (PARTITION BY var2 ORDER BY datetime 
         ROWS BETWEEN 10 PRECEDING AND CURRENT ROW) FROM tbl... 

Leider Median in Postgres nicht implementiert ist, so habe ich mein eigenes Aggregat mit diesem Beispiel:

Das Problem ist, dass dies funktioniert, wenn ich die gesamte Spalte verwenden, aber nicht in einem Fenster (mit OVER-Klausel) Fehler zurückgegeben wird, dass 'vorgeben' sollte definiert werden. Greenplum Dokumentation bestätigt, dass: http://gpdb.docs.pivotal.io/4380/ref_guide/sql_commands/CREATE_AGGREGATE.html

Die Dokumentation und die Rolle von Prefunc ist nicht sehr klar für mich. Haben Sie ein Beispiel für die Definition einer benutzerdefinierten Postgres-Aggregatfunktion, die Windows unterstützt?

Antwort

0

Um ein eigenes Aggregat in GPDB erstellen Sie müssen definieren, ein PREFUNC, der im normalen Postgres kein Parameter ist.

In normalen Postgres benötigt ein Aggregat einen Startzustand (z. B. STYPE=numeric[]) und eine Funktion, die ihm sagt, was zu tun ist, um dem aktuellen Status ein neues Element hinzuzufügen (z. B. SFUNC=array_append). Aber in einem verteilten System wie GPDB, das Daten zwischen Knoten mischt, wie sollte ein Knoten, der Zustände von zwei Orten (dh zwei Arrays) empfängt, beide Zustände kombinieren? Das ist die Rolle von PREFUNC. Dann kann der FINALFUNC schließlich in den einzelnen kombinierten Zustand gerufen und zurückgegeben werden.

In dem Beispiel des Median-Computing müssen Sie lediglich PREFUNC=array_cat, zu der Aggregatdefinition hinzufügen, die Sie von median example code übernommen haben. array_cat nimmt zwei Arrays und gibt sie als ein einzelnes kombiniertes Array zurück. Ich habe es versucht und es funktioniert für mich, sowohl als Aggregat als auch als Fenster.

(Beachten Sie, dass die Version, die numeric[] Werke nimmt, aber aus irgendeinem Grund nicht die anyarray ein. Es scheint aus Gründen als nicht wichtig, um ein Fenster/Aggregatfunktion zu schaffen.)

Für weitere Informationen über Aggregate Siehe die GPDB docs, auf die sich Lukasz bezog.

+0

Es funktioniert, danke für die Erklärung 'PREFUNC' – Lukasz

+0

Großartig, froh, dass es hilfreich @Lukasz war. Wenn Sie die Antwort würdig finden, würde ich mich über eine positive Bewertung und die Anerkennung freuen (http://meta.stackexchange.com/questions/5234/how-does-accepting-an-answer-work). –

1

Ich weiß nicht, ob dies für Greenplum funktioniert. In modernen Versionen von Postgres können Sie jedoch array_agg() als Fensterfunktion verwenden. Also, für Ihre besonders Problem, die Lauf Median:

select (array_agg(var1) over (partition by var2 order by datetime 
           rows between 10 preceding and current row 
          )[6] as running_median 

EDIT:

Eine andere Methode wäre eine Unterabfrage verwenden:

select t.*, 
     (select t2.var1 
     from t t2 
     where t2.var2 = t.var2 and t2.datetime < t.datetime 
     order by t2.datetime desc 
     offset 5 limit 1 
     ) running_median   
from t; 
+0

Greenplum basiert auf [PostgreSQL 8.2.15] (http://greenplum.org/gpdb-sandbox-tutorials/). Ich denke Array_agg() war in dieser Version nicht verfügbar. – McNets

+0

array_agg() ist in GPDB. –

+0

array_agg() funktioniert, aber mit der Gruppe von nicht mit Fenster, ich bekomme immer noch 'ERROR: Aggregatfunktionen ohne prelimfn oder invprelimfn sind noch nicht als Fensterfunktionen unterstützt ' – Lukasz