Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Get average value from the "last" N rows in a table

In my Postgres database table I can find the last 20 entries of cap_cs137 by date order:

select cap_cs137 FROM capintec ORDER BY cap_date DESC LIMIT 20;

I can also get the average:

select avg(cap_cs137) FROM capintec LIMIT 20;

However, how do I combine the above statements to get the average value for the last 20 entries by date order?

We have an outdated RHEL 5.8 server which supports Postgres 8.1.23 and therefore does not allow use of WITH queries.

like image 339
moadeep Avatar asked Dec 30 '13 10:12

moadeep


People also ask

How do you find the average of all 5 rows?

In Excel, have you ever tried to average every 5 rows or columns, that is to say, you need to do these operations: =average (A1:A5), =average(A6:A10), =average(A11:A15),…of course, you can apply the Average function to get the average of every 5 cells every time, but, if there are hundreds and thousands cells in your ...

How do I average every 10 rows in Excel?

This works by shifting the equation AVERAGE(A1:A10) by the row number minus 1 multiplied by 10. Row 1 will be the formula shifted by (1–1)x10=0 rows and Row 2 will be the formula shifted by (2–1)x10=10 rows etc.

How do I find the last 5 values in a row?

You can use AVERAGE, OFFSET, and COUNT functions to average last 5 values in columns. The OFFSET function is used here to return an array of a range with rows, columns, height, and weight. The AVERAGE function then averages the elements in the array.


2 Answers

You can use a CTE:

WITH s AS
    (SELECT cap_cs137 FROM capintec ORDER BY cap_date DESC LIMIT 20)
SELECT avg(cap_cs137) FROM s;

The first query becomes cached as a temporary table "s", then we run the aggregate over it in the final query.

Edit:

It turned out the OP could not use a CTE since he is using an older version of Postgres, so the final answer was a sub-select (which I happen to like less than a CTE purely for readability; but does the exact same thing in this case):

SELECT avg(cap_cs137) FROM
   (SELECT cap_cs137 FROM capintec ORDER BY cap_date DESC LIMIT 20);
like image 73
zxq9 Avatar answered Oct 13 '22 09:10

zxq9


Just use an inner select:

SELECT AVG(cap_cs137)
FROM (SELECT cap_cs137 FROM capintec ORDER BY cap_date DESC LIMIT 20) AS sub;
like image 22
simon Avatar answered Oct 13 '22 09:10

simon