Пользовательская агрегатная функция - PullRequest
0 голосов
/ 02 декабря 2011

Я пытаюсь понять агрегатные функции, и мне нужна помощь.

Так, например, следующий пример:

CREATE OR REPLACE FUNCTION array_median(timestamp[])
  RETURNS timestamp AS
$$
    SELECT CASE WHEN array_upper($1,1) = 0 THEN null ELSE asorted[ceiling(array_upper(asorted,1)/2.0)] END
    FROM (SELECT ARRAY(SELECT ($1)[n] FROM
generate_series(1, array_upper($1, 1)) AS n
    WHERE ($1)[n] IS NOT NULL
            ORDER BY ($1)[n]
) As asorted) As foo ;
$$
  LANGUAGE 'sql' IMMUTABLE;


CREATE AGGREGATE median(timestamp) (
  SFUNC=array_append,
  STYPE=timestamp[],
  FINALFUNC=array_median
)

Я не понимаю структуру / логику, которая должна идтиоператор выбора в самой статистической функции.Может кто-нибудь объяснить, что такое поток / логика?

Я пишу агрегат, странный, что возвращение всегда первая строка, которую он когда-либо видит.

1 Ответ

2 голосов
/ 02 декабря 2011

Вы показываете медианное вычисление, но хотите первое текстовое значение, которое вы видите?

Ниже описано, как это сделать. Предполагая, что вы хотите первое ненулевое значение, то есть. Если нет, вам нужно будет отслеживать, есть ли у вас значение или нет.

Функция накопителя записана в виде plpgsql и sql - функция plpgsql позволяет вам использовать имена переменных и отлаживать их тоже. Он просто использует COALESCE против предыдущего накопленного значения и нового значения и возвращает первое ненулевое значение. Итак, как только у вас в аккумуляторе есть ненулевое значение, все остальное игнорируется.

Вы также можете рассмотреть оконную функцию first_value для такого рода вещей, если вы используете современную (8.4+) версию PostgreSQL.

http://www.postgresql.org/docs/9.1/static/functions-window.html

НТН

BEGIN;

CREATE FUNCTION remember_first(acc text, newval text) RETURNS text AS $$
BEGIN
    RAISE NOTICE '% vs % = %', acc, newval, COALESCE(acc, newval);
    RETURN COALESCE(acc, newval);
END;
$$ LANGUAGE plpgsql IMMUTABLE;

CREATE FUNCTION remember_first_sql(text,text) RETURNS text AS $$
    SELECT COALESCE($1, $2);
$$ LANGUAGE SQL IMMUTABLE;

-- No "initcond" means we start out with null
--      
CREATE AGGREGATE first(text) (
    sfunc = remember_first,
    stype = text
);

CREATE TEMP TABLE tt (t text);
INSERT INTO tt VALUES ('abc'),('def'),('ghi');

SELECT first(t) FROM tt;

ROLLBACK;
...