views:

40

answers:

2

Assuming that my subquery yields a number of rows with the columns (x,y), I would like to calculate the value avg(abs(x-mean)/y). where mean effectively is avg(x).

select avg(abs(x-avg(x))/y) as incline from subquery fails because I cannot nest aggregation functions. Nor can I think of a way to calculate the mean in a subquery while keeping the original result set. An avgdev function as it exists in other dialects would not exactly help me, so here I am stuck. Probably just due to lack of sql knowledge - calculating the value from the result set in postprocessing is easy.

Which SQL construct could help me?

Edit: Server version is 8.3.4. No window functions with WITH or OVER available here.

+1  A: 

Not sure I understand you correctly, but you might be looking for something like this:

SELECT avg(x - mean/y)
FROM (
  SELECT x, 
         y, 
         avg(x) as mean over(partition by your_grouping_column) 
  FROM your_table
) t

If you do not need to group your results to get the correct avg(x) then simply leave out the "partition by" using an empty over: over()

a_horse_with_no_name
`select x, y, avg(x) as mean over() from (..my subquery here..) as sub;` fails with an `ERROR: syntax error at or near "over"` for me.
relet
Window functions seems to be a 8.4 feature, and the server I am querying is 8.3.4. Thanks anyway. :]
relet
That's one of the reaons you should always mention your Postgres version ;)
a_horse_with_no_name
I will learn. ;)
relet
A: 

One option I found is to use a temporary table:

begin; 
  create temporary table sub on commit drop as (...subquery code...);
  select avg(abs(x-mean)/y) as incline from (SELECT x, y, (SELECT avg(x) FROM sub) AS mean FROM sub) as sub2;
commit;

But is that overkill?

relet