Ist das ein Bug oder verstehe ich last_value() nicht richtig?

Hier ist meine Abfrage:

SELECT ticker_id, date, close,
	date_trunc('month',date) as dt,
	first_value(close) OVER (w),
	last_value(close) OVER (w),
	row_number() OVER (w)
FROM eod
WHERE ticker_id=50170
AND	date_trunc('month',date) = '2014-05-01 00:00:00+02'
		WINDOW w AS (
					PARTITION BY ticker_id,
					date_trunc('month',date)
					ORDER BY date
				)	
ORDER by date

Diese Liefert

ticker_id date close dt first_value last_value row_number
50170 2014-05-26 29,54 € 2014-05-01 00:00:00+02 29,54 € 29,54 € 1
50170 2014-05-27 29,34 € 2014-05-01 00:00:00+02 29,54 € 29,34 € 2
50170 2014-05-28 29,51 € 2014-05-01 00:00:00+02 29,54 € 29,51 € 3
50170 2014-05-29 29,40 € 2014-05-01 00:00:00+02 29,54 € 29,40 € 4
50170 2014-05-30 29,90 € 2014-05-01 00:00:00+02 29,54 € 29,90 € 5

Mein Verständis war, das last_value in diesem Beispiel immer 29,90€ liefern sollte so wie first_value immer 29,54€ liefert.

Versteh ich das falsch oder ist das ein Bug?

Mein System:
pgadmin4 8.7

postgres=# SELECT version();
                                                      version                                                      
-------------------------------------------------------------------------------------------------------------------
 PostgreSQL 15.6 (Debian 15.6-0+deb12u1) on x86_64-pc-linux-gnu, compiled by gcc (Debian 12.2.0-14) 12.2.0, 64-bit
(1 Zeile)

Das liegt an der Standardefinition des verwendeten Fenster bei Verwund von ORDER BY. Im Handbuch wird sogar explizit auf das Problem bei last_value hingewiesen:

Du musst für last_value() eine ander Definition des Fensters verwenden:

last_value(close) 
  over (
    partition by ticker_id, date_trunc('month', date) 
    by date
    between unbounded preceding and unbounded following
  )

Das between unbounded preceding and unbounded following ist der entscheidende Unterschied

1 „Gefällt mir“

Schau mal nach der Range Klausel

Note that first_value, last_value, and nth_value consider only the rows within the “window frame”, which by default contains the rows from the start of the partition through the last peer of the current row. This is likely to give unhelpful results for last_value and sometimes also nth_value. You can redefine the frame by adding a suitable frame specification (RANGE, ROWS or GROUPS) to the OVER clause. See Section 4.2.8 for more information about frame specifications.

Du kannst dir auch mal dieses Beispiel anschauen:

Danke für den Hinweis :slight_smile: