2010-08-25 5 views
1

Предполагая, что мой subquery дает количество строк со столбцами (x, y), я хотел бы вычислить значение avg(abs(x-mean)/y). где mean эффективно avg(x).Избегайте встраивания функций агрегации в PostgreSQL 8.3.4

select avg(abs(x-avg(x))/y) as incline from subquery не работает, потому что я не могу установить функции агрегации. Я также не могу думать о способе вычисления среднего значения в подзапросе, сохраняя при этом исходный набор результатов. Функция avgdev, поскольку она существует в других диалектах, не поможет мне, поэтому здесь я застрял. Вероятно, из-за отсутствия знаний sql - вычисление значения из набора результатов в постобработке легко.

Какой SQL-конструктор может мне помочь?

Редактировать: Версия сервера - 8.3.4. Нет функций окна с WITH или OVER.

+0

Я полагаю, что вопрос это ... если вам действительно нужно действительно такое поведение ... есть ли причина, по которой вы не можете пройти обновление? – xenoterracide

+1

, когда depesz делает свою «ожидающую» серию, он иногда показывает предыдущий способ сделать это ... вы, возможно, захотите посмотреть его ожидания на оконные функции или подобное. – xenoterracide

+0

Это было бы тогда: http://www.depesz.com/index.php/2009/01/21/waiting-for-84-window-functions/ - спасибо за этот указатель. – relet

ответ

0

Один вариант я нашел, чтобы использовать временную таблицу:

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; 

Но что избыточна?

+2

Вам не нужна временная таблица, просто введите код подзапроса в том же месте, где у вас есть таблица –

1

Не уверен, что я правильно понимаю вас, но вы можете искать что-то вроде этого:

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

Если вам не нужно группировать результаты, чтобы получить правильный ср (х), то просто оставить вне «раздела,» используя порожнего: over()

+0

'select x, y, avg (x) как среднее значение над() из (..my подзапроса здесь ..) как sub;' fail с ошибкой синтаксиса «ERROR: синтаксис» или «рядом» для меня. – relet

+1

Функции окна, по-видимому, являются функцией 8.4, а сервер, к которому я обращаюсь, - это 8.3.4. Спасибо, в любом случае. :] – relet

+2

Это одна из причин, по которой вы всегда должны упоминать свою версию Postgres;) –

1

если ваши наборы данных не слишком велики, вы можете накапливать их в массив, а затем вернуть угол наклона от функции:

create type typ as (x numeric, y numeric); 

create aggregate array_accum(sfunc = array_append, 
           basetype = anyelement, 
           stype = anyarray, 
           initcond = '{}'); 

create or replace function unnest(anyarray) returns setof anyelement 
          language sql immutable strict as $$ 
    select $1[i] from generate_series(array_lower($1,1), array_upper($1,1)) i;$$; 

create function get_incline(typ[]) returns numeric 
       language sql immutable strict as $$ 
    select avg(abs(x-(select avg(x) from unnest($1)))/y) from unnest($1);$$; 

select get_incline((select array_accum((x,y)::typ) from subquery)); 

вид образца для тестирования:

create view subquery as 
select generate_series(1,5) as x, generate_series(1,6) as y; 
Смежные вопросы