2017-06-05 1 views
1

Ich möchte den ersten Wert einer Spalte und den letzten Wert der zweiten Spalte in einer Zeile für eine bestimmte Partition haben. Dafür habe ich diese Abfrage:Erster und letzter Wert der Fensterfunktion in einer Zeile in PostgreSQL

SELECT DISTINCT 
b.machine_id, 
batch, 
timestamp_sta, 
timestamp_stp, 
FIRST_VALUE(timestamp_sta) OVER w AS batch_start, 
LAST_VALUE(timestamp_stp) OVER w AS batch_end 
FROM db_data.sta_stp AS a 
JOIN db_data.ll_lu AS b 
ON a.ll_lu_id=b.id 
WINDOW w AS (PARTITION BY batch, machine_id ORDER BY timestamp_sta) 
ORDER BY timestamp_sta, batch, machine_id; 

Aber wie Sie im Bild sehen können, zurückgegebenen Daten in batch_end Spalte nicht korrekt sind.

batch_start Spalt haben korrekten ersten Wert von timestamp_sta Spalt. Jedoch batch_end sollte "2012-09-17 10:49:45" sein und es entspricht timestamp_stp aus derselben Zeile.

Warum ist es so?

enter image description here

Antwort

3

Von syntax documentation:

Die frame_clause gibt den Satz von Zeilen bilden, die Fensterrahmen, die eine Untermenge der aktuellen Partition, für die Fensterfunktionen, die auf dem Rahmen wirken, anstatt die ganze Partition. Der Rahmen kann im RANGE- oder ROWS-Modus angegeben werden. In jedem Fall läuft es vom frame_start zum frame_end. Wenn frame_end nicht angegeben wird, wird standardmäßig CURRENT ROW verwendet.

Ein frame_start von UNBOUNDED PRECEDING bedeutet, dass der Frame mit der ersten Zeile der Partition beginnt, und ähnlich ein frame_end von UNBOUNDED FOLLOWING bedeutet, dass der Frame mit der letzten Zeile der Partition endet.

und function list

last_value (Wert vorhanden) zurückgibt Wert in der Zeile ausgewertet, die die letzte Zeile des Fensterrahmens ist

So richtig SQL sein sollte:

SELECT DISTINCT 
b.machine_id, 
batch, 
timestamp_sta, 
timestamp_stp, 
FIRST_VALUE(timestamp_sta) OVER w AS batch_start, 
LAST_VALUE(timestamp_stp) OVER w AS batch_end 
FROM db_data.sta_stp AS a 
JOIN db_data.ll_lu AS b 
ON a.ll_lu_id=b.id 
WINDOW w AS (PARTITION BY batch, machine_id ORDER BY timestamp_sta range between unbounded preceding and unbounded following) 
ORDER BY timestamp_sta, batch, machine_id; 
+0

Große, das ist es! Ich habe gerade auch diese Handbuchseite entdeckt, aber ich habe immer noch nicht ganz verstanden, wie es funktioniert. Danke für das funktionierende Beispiel. –

+1

Leider glaube ich nicht, dass es das erwartete Ergebnis zurückgibt. – klin

+0

@klin Ja, hat es für mich getan. Was ist falsch an dieser Lösung? –

3

Die Erklärungen von @ £ Ukasz Kamiński löst den Kern des Problems.

Die last_value sollte jedoch durch max() ersetzt werden. Sie sortieren nach timestamp_sta, so dass der letzte Wert der Wert timestamp_sta ist, der mit timestamp_stp in Beziehung steht oder nicht. Auch ich würde nach den zwei Feldern sortieren.

SELECT DISTINCT 
    b.machine_id, 
    batch, 
    timestamp_sta, 
    timestamp_stp, 
    FIRST_VALUE(timestamp_sta) OVER w AS batch_start, 
    MAX(timestamp_stp) OVER w AS batch_end 
FROM db_data.sta_stp AS a 
JOIN db_data.ll_lu AS b 
ON a.ll_lu_id=b.id 
WINDOW w AS (PARTITION BY batch, machine_id 
      ORDER BY timestamp_sta,timestamp_stp 
      RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING) 
ORDER BY timestamp_sta, batch, machine_id; 

http://rextester.com/UTDE60342

Verwandte Themen