2016-03-21 3 views
0

Я пытаюсь написать функцию в postgre sql, чтобы получить среднее значение по трем столбцам. Я написал следующую функцию:Создайте функцию для вычисления среднего значения из трех значений

create function xcol_avg (col1, col2, col3) 
returns numeric as $$ 

begin 

return (coalesce(col1, 0) + coalesce(col2,0) +coalesce(col3, 0))/ 
case when (col 1 is null or col1 = 0 then 0 else 1 end + 
case when (col 2 is null or col2 = 0 then 0 else 1 end + 
case when (col 3 is null or col3 = 0 then 0 else 1 end; 

end 

В чем проблема с моим кодом? Кроме того, есть ли способ заставить функцию возвращать значение null, если она заканчивается делением на 0? Любая помощь действительно ценится. Спасибо!

+0

В чем ваш вопрос? –

+0

@ Кристен, я добавил свой ответ. Надеюсь, это даст вам достаточно информации по этому вопросу. У вас есть различные проблемы с вашей функцией. Предлагаю вам ознакомиться с руководством: http://www.postgresql.org/docs/current/static/sql-createfunction.html –

ответ

1

На самом деле вы можете сделать функцию, которая будет использовать переменное количество аргументов и в зависимости от их числа вычислить среднее значение. В Postgres есть слово VARIADIC для таких вещей:

функции SQL может быть объявлен принимать переменное количество аргументов, так долго, как все «дополнительные» аргументы одного и того же типа данных

код функции:

CREATE FUNCTION xcol_avg(numeric, VARIADIC numeric[]) 
    RETURNS numeric 
    LANGUAGE plpgsql 
    IMMUTABLE 
AS $$ 
BEGIN 
    RETURN (SELECT AVG(vals) FROM unnest($2 || ARRAY[$1]) t(vals)); 
END; 
$$; 

Используйте случай с различным числом аргументов:

select xcol_avg(1,6); -- returns 3.5 
select xcol_avg(1,5.5,4); -- returns 3.5 
select xcol_avg(1,2,3,4,5,6,7); -- returns 4 

Нажмите на эту Button попробовать это в Интернете.

Пояснение:

  • Маркировка функции как IMMUTABLE улучшает время выполнения, позволяя оптимизатор предварительно оценить функцию. Неизменяемые функции не могут изменять базу данных и гарантированно всегда возвращать те же результаты при вызове с одним и тем же входом.
  • Объявление последнего параметра функции как VARIADIC, который должен иметь тип массива, позволяет предоставить необязательные аргументы, которые будут переданы функции в виде массива. Обратите внимание, что вы явно не пишете массив, вы просто перечисляете свои параметры, как обычно.
  • unnest() - это функция, возвращающая набор строк путем расширения массива. Другими словами, это «распаковка» элементов массива в отдельные строки.
  • || - это оператор массива, который обеспечивает конкатенацию массива к массиву. Здесь он служит для соединения первого (обязательного) аргумента с остальным, заданным в массиве VARIADIC.
  • AVG() - это совокупная функция, которая вычисляет среднее значение всех входных значений. В нашем случае это займет «распакованные» строки из столбца с именем vals и вычислить среднее значение.

С помощью этого решения вам не нужно беспокоиться о делении на ноль, требуется по крайней мере один аргумент и avg() делает работу, которую вы хотели сделать вручную путем создания знаменателя.

Применить его в запросе:

Эта функция также будет работать для вычисления в среднем несколько столбцов в строке.Рассмотрим таблицу tbl с колоннами name, cost1, cost2, cost3 и ниже высказыванием:

SELECT 
    name, cost1, cost2, cost3, 
    xcol_avg(cost1, cost2, cost3) AS average_cost 
FROM tbl 

Для получения более общей информации о CREATE FUNCTIONthe resourceful documentation проверки.