У меня часто возникают запросы с той же комбинацией агрегатных функций. Например.Как повторно использовать выражение с агрегатами в PostgreSQL без замедления
SELECT
my_id,
sum(a * weight)/nullif(sum(CASE WHEN a IS NOT NULL THEN weight END), 0) AS a,
sum(b * weight)/nullif(sum(CASE WHEN b IS NOT NULL THEN weight END), 0) AS b
FROM my_table
GROUP BY my_id
Я хотел бы избежать повторения одних и тех же выражений снова и снова. Было бы здорово, чтобы получить тот же результат с новой функцией weighted_avg
:
SELECT
my_id,
weighted_avg(a, weight) AS a,
weighted_avg(b, weight) AS b
FROM my_table
GROUP BY my_id
Единственным способом сделать это, я не знаю, является использование CREATE AGGREGATE
с промежуточным состоянием и SFUNC
который вызывается для каждой строки. К сожалению, это намного медленнее исходного запроса, что делает его непригодным в моем случае.
Я полагаю, мой идеальным решением будет выглядеть
CREATE AGGREGATE FUNCTION weighted_avg(x float, weight float)
RETURNS float AS $$
SELECT sum(x * weight)/nullif(sum(CASE WHEN x IS NOT NULL THEN weight END), 0)
$$ language SQL IMMUTABLE;
и быть инлайн при выполнении запроса. Но я не могу найти ничего подобного, поддерживаемого Postgres.
Использование функции, вероятно, всегда будет немного медленнее, чем просто использовать выражения в исходном коде. –
У меня все в порядке с некоторыми издержками, но реализация plpgsql с 'CREATE AGGREGATE' занимает в 4 раза больше времени для выполнения в моем случае. Поэтому я бы сохранил оригинальные выражения, которые приемлемы, но я надеялся на лучшее решение. –
Используйте подзапрос в 'FROM' для вычисления входных выражений один раз. –