2016-06-12 24 views
0

alle! Ich habe folgendes Szenario: 1. eine ziemlich komplizierte SELECT-Anweisung. Ich brauche die ersten n Zeilen aus der Ergebnismenge, rufe $ sql mit Joins und mehreren WHERE-Klauseln auf. 2. eine Aggregation SELECT-Anweisung, wo ich alle Ergebnisse aus der komplizierten select-Anweisung verwenden, die wie folgt aussieht:PostgreSQL wählen und aggregieren

SELECT SUM(a), (SELECT DISTINCT....) etc. 

Derzeit ist die Implementierung so aussieht, dass die beiden Schritte werden separat in einem Perl-Code.

  1. zunächst ein Cursor wird „
  2. dann der erste n Treffer geholt Köter CURSOR OHNE HOLD FOR $ sql‘ ERKLäREN
  3. dann kommt die Zusammenfassung Aufruf der ganzen $ sql in die Erklärung interpoliert wird.:

    SELECT SUM(foo) AS sum1 
    FROM A, ($sql) AS B 
    WHERE A.doc=? AND A.id=B.id 
    

so teuer ist, nimmt $ sql < 1 sec und zweimal getan. Natürlich würde Ich mag den zweiten Anruf, wenn möglich zu vermeiden. Also möchte ich eine Funktion schreiben, die die $ sql (die dynamisch generiert wird) und die Anzahl der Datensätze zurückgeben, gibt die Datensätze zurück, speichert aber die gesamte Ergebnismenge, um die Abfrage erneut zu vermeiden. Die Ergebnismenge ist> 6000 Zeilen.

Da ich jedoch in PL/pgSQL nicht stark bin, kann ich es mir nicht als gespeicherte Prozedur vorstellen. Soll ich eine Temp erstellen? Tabelle mit der Ergebnismenge der Tannen-Abfrage und später im zweiten Schritt verwenden? Oder besser, die Auswahl und die Zusammenfassung in einem Schritt zu machen und das Ergebnis in einem Temp zu speichern. Tabelle? Programmatisch habe ich den zweiten gewählt, aber ich brauche dazu noch einen Rat.

Und ich würde auch jede Codeskizze sehr schätzen, um PL/pgSQL im Allgemeinen besser zu verstehen und zu sehen, wie man diese Art von 'SELECT and aggregate' Problem löst und zwei Arten von Werten zurückgibt. Vielen Dank im Voraus.

+0

Sie können versuchen, mit 'INTO' SELECT und temporäre Tabelle erstellen. – Adam

Antwort

0

Überprüfen der manuelle here und here:

Wenn eine Aggregatfunktion als eine Fensterfunktion verwendet wird, aggregiert über die Reihen innerhalb der Fensterrahmen der aktuellen Zeile. Ein Aggregat, das mit ORDER BY und der Standardfensterrahmendefinition verwendet wird, erzeugt ein Verhalten vom Typ "laufende Summe", das möglicherweise nicht gewünscht ist. Um eine Aggregation über die gesamte Partition zu erhalten, lassen Sie ORDER BY weg oder verwenden Sie ROWS BETONEN UNBOUNDED PRECEDING UND UNBOUNDED FOLLOWING. Andere Rahmenspezifikationen können verwendet werden, um andere Effekte zu erhalten.

Angenommen t ist die dynamische Abfrage:

select * 
from (
    select *, 
     sum(foo) over() as the_sum, 
     row_number() over(order by bar) as rn 
    from t 
) s 
where rn < 3 
; 
foo | bar | the_sum | rn 
-----+-----+---------+---- 
    1 | a |  6 | 1 
    2 | b |  6 | 2 

t:

create table t (foo int, bar text); 
insert into t (foo, bar) values 
(1,'a'),(2,'b'),(3,'c'); 
Verwandte Themen