пользовательские переменные в postgresql

Здравствуйте!

В mysql есть возможность использовать пользовательские переменные в запросах, что позволяет оптимизировать определенные вычисления.

Простой пример - есть таблица pogoda с двумя полями - t и d, t - это временная метка, а d - это результат измерения погоды. Требуется найти максимальный перепад.

Срабатывает следующая конструкция:

Код:
SET @data=NULL, @next_data=NULL, @max_value=0;

SELECT @next_data:=`d` `nextdata`,IF (@next_data - @data>@max_value, @max_value:=@next_data-@data, @max_value), @data:=d FROM `pogoda`;

SELECT @max_value;

Соль в том, что на n-й строке мы знаем значение d на (n-1)-й строке, и можем вычислить разницу за один проход.

Собственно, вопрос в чем: можно ли такую же конструкцию выполнить на postgresql? Без хранимых процедур, именно вот так, по ходу выполнения запроса. Если реально, то приведите пожалуйста текст запроса.

Заранее большое спасибо!

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Вообще-то в 9-ке уже можно

Вообще-то в 9-ке уже можно писать просто блок кода без хранимой процедуры, например:

DO LANGUAGE plpgsql $$
 DECLARE
 var record;
 
 BEGIN
 FOR vr IN SELECT tablename FROM pg_tables WHERE tableowner = 'marc' AND schemaname NOT IN ('pg_catalog', 'information_schema')
 LOOP
   EXECUTE 'GRANT SELECT ON ' || vr.tablename || ' TO toto';
 END LOOP;
 END
 $$;

Спасибо за подсказку. Правда,

Спасибо за подсказку. Правда, увы, блоки кода, не оформленные в процедуру/функцию, судя под документации, не возвращают значений и не принимают параметров, поэтому состряпал вот такой вариант:

drop function if exists pg_temp.temp_func();
create function pg_temp.temp_func() returns int as $$
DECLARE
prev integer;
curr integer;
max_ integer;
begin
max_ := 0;
prev := 0;
FOR curr IN SELECT d FROM pogoda
LOOP
if (curr - prev > max_) then
max_ := curr - prev;
end if;
prev := curr;
END LOOP;
return max_;
end
$$ language plpgsql;

select pg_temp.temp_func();

Скажите пожалуйста, это единственное, на что я, так сказать, могу расчитывать или можно как-то покороче?

тут должна быть

тут должна быть сортировка
SELECT d FROM pogoda

возможен такой вариант подойдет

SELECT max(v)
FROM (
SELECT p.curr- lag(p.curr) over (ORDER BY p.curr) v
  FROM pogoda p
 ORDER BY p.curr) s

Спасибо за ответ, не знал про

Спасибо за ответ, не знал про функцию lag, красиво получилось. Что касается сортировки - в случае работы mysql можно выкрутиться, например, составным индексом на (t,d), если в выборке не запретить его использование, то выборка идёт по индексу и даные получаются отсортированные по t.

Если результат выборки

Если результат выборки использует отсортированный диапазон, не оставлял бы это на откуп оптимизатору, ведь может добавиться еще индекс или изменится структура таблицы, а ошибка будет ой как не очевида.

Согласен, метод на грани

Согласен, метод на грани фола. Добавление нового столбца/индекса испортит обедню махом. Просто в данном контексте я говорю про конкретный случай, не предусматривающий ни добавления нового столбца ни модификацию индексов.

Опции просмотра комментариев

Выберите предпочитаемый вами способ показа комментариев и нажмите "Сохранить настройки" для активации изменений.

Back to top

(С) Виктор Вислобоков, 2008-2023