2017-02-01 2 views
1

Ich versuche, wählen Sie den Maximalwert aus den letzten zwei JahrenPostgresql: Mit einer Fensterfunktion den MAX-Wert von einem Datumsbereich

Zum Beispiel zu wählen, wenn ich eine Tabelle wie folgt:

|person_id | pass_or_fail | timestamp| 
|----------|--------------|-----------| 
|1234  | 1   | 1990-01-01| 
|1234  | 0   | 1995-01-01| 
|1234  | NULL   | 1995-12-12| 
|6789  | 0   | 1990-01-01| 
|6789  | 0   | 1991-01-01| 
|6789  | 1   | 1995-01-01| 
|6789  | 1   | 1996-01-01| 
|6789  | 0   | 1997-01-01| 
|6789  | NULL   | 1997-03-03| 

ich folgendes aus meiner Anfrage erhalten mag:

person_id |highest_grade_from_past_two_years | pass_or_fail | timestamp 
1234  |1         | 1   | 1990-01-01 
1234  |0         | 0   | 1995-01-01 
1234  |0         | NULL   | 1995-12-12 
6789  |0         | 0   | 1990-01-01 
6789  |0         | 0   | 1991-01-01 
6789  |1         | 1   | 1995-01-01 
6789  |1         | 1   | 1996-01-01 
6789  |1         | 0   | 1997-01-01 
6789  |1         | NULL   | 1997-03-03 

Wie kann ich schreibe meine Fensterfunktion, um mir dieses Ergebnis?

Antwort

0

Ich sehe nicht, wie diese Abfrage mit Fensterfunktionen geschrieben wird. Version ohne Fenster:

SELECT t1.person_id, 
     max(t2.pass_or_fail) AS highest_grade_from_past_two_years, 
     t1.pass_or_fail, 
     t1.timestamp 
FROM t AS t1 
    JOIN t AS t2 ON (
      t1.person_id = t2.person_id 
      AND t2.timestamp < t1.timestamp + '2 year'::interval 
      AND t2.timestamp <= t1.timestamp 
    ) 
GROUP BY 1, 3, 4 
+0

Die zweite Tabelle oben ist, wie ich meine Abfrageergebnisse aussehen soll. Ich arbeite nur mit einer Tabelle –

+0

beide Tabellen ist das gleiche, ich benutze es zu vermeiden, mit Unterabfrage in Select-Anweisung - es läuft für jede Zeile separat –

0

Durch die Zusammenarbeit mit aktuellem Jahr Beitritt - 1

select p1.person_id, p1.pass_or_fail, p1.timestamp, 
     case when coalesce(p1.pass_or_fail,0) > coalesce(p2.pass_or_fail,0) 
      then coalesce(p1.pass_or_fail,0) else coalesce(p2.pass_or_fail,0) end as highest_grade_from_past_two_years 
from person p1 
    left join person p2 
    on p1.person_id = p2.person_id 
     and extract(year from p2.timestamp) = extract(year from p1.timestamp) - 1 
order by p1.person_id, p1.timestamp 

(falls vorhanden);

prüfen: http://rextester.com/BNPW52530

0

Ich sehe keine offensichtliche Möglichkeit Fensterfunktionen zu verwenden. Eine korrelierte Unterabfrage oder seitlich verbinden funktionieren würde:

select t.*, 
     (select max(t2.pass_or_fail) 
     from t t2 
     where t2.person_id = t.person_id and 
       t2.timestamp <= t.timestamp and 
       t2.timestamp >= t.timestamp - interval '2 year' 
     ) as highest_grade_from_past_two_years 
from t; 

Ich denke, die nächstgelegene Sie mit Fensterfunktionen erhalten können, ist eine Bereichsangabe. Postgres unterstützt jedoch nicht die preceding Spezifikation mit range.

+0

Es ist nicht sehr gut, Unterabfrage in Select - es für jede Zeile getrennt . –

+0

@RomanTkachuk. . . Ich glaube nicht, dass Sie SQL so gut verstehen wie ich. Eine korrelierte Unterabfrage ist hier in Ordnung. Es läuft schneller mit einem Index auf 't (person_id, timestamp, pass_or_fail)'. –

Verwandte Themen