Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

PostgreSQL aggregate or window function to return just the last value

I'm using an aggregate function with the OVER clause in PostgreSQL 9.1 and I want to return just the last row for each window. The last_value() window function sounds like it might do what I want - but it doesn't. It returns a row for each row in the window, whereas I want just one row per window

A simplified example:

SELECT a, some_func_like_last_value(b) OVER (PARTITION BY a ORDER BY b)
FROM
(
    SELECT 1 AS a, 'do not want this' AS b
    UNION SELECT 1, 'just want this'
) sub

I want this to return one row:

1, 'just want this'
like image 822
EMP Avatar asked Nov 30 '11 02:11

EMP


1 Answers

DISTINCT plus window function

Add a DISTINCT clause:

SELECT DISTINCT a
     , last_value(b) OVER (PARTITION BY a ORDER BY b
                           RANGE BETWEEN UNBOUNDED PRECEDING AND UNBOUNDED FOLLOWING)
FROM  (
   VALUES
     (1, 'do not want this')
    ,(1, 'just want this')
   ) sub(a, b);

More about DISTINCT:

  • PostgreSQL: running count of rows for a query 'by minute'

Simpler and faster with DISTINCT ON

PostgreSQL also has this extension of the SQL standard:

SELECT DISTINCT ON (a)
       a, b
FROM  (
   VALUES
     (1, 'do not want this')
   , (1, 'just want this')
   ) sub(a, b)
ORDER  BY a, b DESC;

More about DISTINCT ON and possibly faster alternatives:

  • Select first row in each GROUP BY group?

Simple case with plain aggregate

If your case is actually as simple as your demo (and you don't need additional columns from that last row), a plain aggregate function will be simpler:

SELECT a, max(b)
FROM  (
   VALUES
     (1, 'do not want this')
   , (1, 'just want this')
   ) sub(a, b)
GROUP  BY a;
like image 74
Erwin Brandstetter Avatar answered Oct 23 '22 04:10

Erwin Brandstetter