Предисловие:
7 лет пашу на MSSQL и иногда прикасаюсь к MySQL. С PostgreSQL давно собирался плотно познакомится, но все как-то времени не хватало. Сейчас, дома, по вечерам пытаюсь свой проект из MSSQL перевести на PostgreSQL. Честно признаюсь, видимо все таки привычка - вторая натура... Никак не постичь до конца мне всю прелесть Postgre... Например функции...
А посему прошу помощи...
Имеем (структура примитизирована умышленно):
Таблица Accounts (acc_id, acc_parent, acc_name) - перечень статей
Таблица Transaction (tran_id, acc_id, tran_date, tran_value) - список транзакций проводящихся по конкретной статье.
Задача: Выборка данных за месяц для заполнения элемента управления TreeView. Родители групп должны отображать сумму значений подчиненных. Необходима рекурсия.
Решение:
В этой функции я провожу рекурсию для того чтобы получить сумму всех подчиненных группы.
Вызов: GetSUM(acc_id, tran_date)
DECLARE
N alias for $1;
DTYPE int4 default 0;
row accounts%rowtype;
tmp int4=0;
results int4 default 0;
BEGIN
select documents.doc_type_id into DTYPE from documents where documents.doc_id=N;
if DTYPE = 1 then
elseif DType = 2 then
end if;
if exists(select 1 from accounts where acc_parent = N) then
for row in select * from accounts where acc_parent = N loop
tmp = 0;
if row.acc_type_id = 3 then
select inserter(row.acc_id, D) into tmp;
else
select SUM(transactions.tran_value) into tmp from transactions where transactions.acc_id = row.acc_id and transactions.tran_date = D;
end if;
if not tmp is null then
results := results + tmp;
end if;
end loop;
else
select SUM(transactions.tran_value) into results from transactions where transactions.acc_id = N and transactions.tran_date = D;
end if;
return row;
END;
И в принципе можно было бы спокойно собрать таблицу простым
SELECT acc_id, acc_parent ,acc_name, GetSUM(acc_id,tran_date),GetSUM(acc_id,tran_date+'1 days'::interval) и так все дни месяца... Но вот тут-то и начинается мой ступор... Хотелось бы в идеале получить функцию которая возвращала бы таблицу количество колонок в которой менялось бы в зависимости от месяца который будет указан в параметре.
Не сочтите за лень. Реально не могу, видимо, чего-то осознать. Неделю потратил на прочтение, к сожалению, весьма сдержанной информации. Все примеры с функциями сводятся к обязательному перечислению параметров на входе, что на мой взгляд не очень удобно. Что же касается кросс-выборки - то это пока остается в мечтах потому как то что нашел не работает...
Сейчас ночь и вникать во
Сейчас ночь и вникать во что-то мне трудно. Увидел знакомое слово "рекурсия" и на всякий случай даю эту ссылку:
http://postgresql.ru.net/manual/queries-with.html
возможно оно вам поможет обойтись без функции, одним SELECT
Разумеется функции, которые возвращают тип данных "запись" в PostgreSQL есть. Читаните здесь:
http://postgresql.ru.net/docs/FAQ_russian.html#item4.18
и здесь:
http://postgresql.ru.net/manual/queries-table-expressions.html#QUERIES-T...
и здесь:
http://postgresql.ru.net/node/35409
спасибо за ссылку на рекурсию :)
остальные я уже посещал...
В принципе остался один, но достаточно важный для меня вопрос (здесь уже озвучивался похожий)... Как получить из функции результат запроса с неопределенным количеством колонок. В моем случае конечно проще было бы написать три функции для 31-го дня, 30 и 28... Но хотелось бы все таки понять - возможно ли исполнить функцию:
declare
r record;
st text;
begin
select gr() into st;
--получили длинную строку запроса
for r in EXECUTE st loop
return next r;
end loop;
return;
end
не объявляя колонки в виде
select * from getrows() as dept(acc_type_id int, acc_name varchar, d1 int,d2 int..............................)
существует способ привести все это к виду, например
select * from getrows('April')?
Насколько я понимаю, функция,
Насколько я понимаю, функция, которая возвращает тип RECORD не ограничена в количестве возвращаемых значений в строке. Хотя не пробовал, не пробовал...