#sql #postgresql
#sql #postgresql
Вопрос:
У меня есть функция Postgresql, которая возвращает несколько значений в виде записи. Мне нужно принять тип записи и проанализировать как несколько столбцов. Я вызываю функцию внутри select
оператора, как показано ниже:
SELECT bank_id, myfunction(document_id,'DF') FROM timeline_chronicle WHERE document_id = 102;
Приведенное выше утверждение возвращает следующее:
--------------------------------------
bank_id | record
----------------------------------------
9006 | (DOCUMENT_IS_ACCEPTED,"2020-07-03 16:37:28","2020-07-03 16:41:58",270)
----------------------------------------------------------------------------------
Но мне нужна версия ниже
--------------------------------------
bank_id | event_type | start_time | end_time | difference |
-----------------------------------------------------------------------
9006 | DOCUMENT_IS_ACCEPTED | 2020-07-03 16:37:28 | 2020-07-03 16:41:58 | 270
----------------------------------------
Кроме того, я попробовал нижеприведенную версию, но в любом случае не работает:
SELECT bank_id, myfunction(document_id,'DF') as (event_type text,start_time TIMESTAMP,end_time TIMESTAMP,difference integer) FROM timeline_chronicle WHERE document_id = 102;
Версия Postgre: 9.6.18. Моя функция Postgre приведена ниже:
CREATE OR REPLACE FUNCTION myfunction(doc_id integer,oper_name2 text)
RETURNS RECORD AS $$
DECLARE
start_tim timestamp(0) without time zone;
end_tim timestamp(0) without time zone;
event_typo text;
tim_diff integer;
ret RECORD;
BEGIN
start_tim := (SELECT to_timestamp(MIN(created_at))::timestamp FROM table WHERE document_id = 62);
SELECT event_type,created_at INTO event_typo,end_tim FROM (
SELECT document_id,oper_name,event_type,to_timestamp(created_at)::timestamp as created_at,
case when event_type in ('DOCUMENT_IS_DENY','DOCUMENT_IS_ACCEPTED') then 2 else 1 end as status
FROM table
WHERE document_id = 62 order by created_at asc
) s WHERE status = 2 order by created_at asc limit 1;
tim_diff:= (select extract(epoch from (end_tim-start_tim)));
SELECT event_typo,start_tim,end_tim,tim_diff INTO ret;
RETURN ret;
END;
$$ LANGUAGE plpgsql;
Комментарии:
1. Какой тип данных created_at? Почему это не временная метка?
2. В таблице это
integer
тип3. Приведение
::timestamp
бесполезно, посколькуto_timestamp()
уже возвращает временную метку.
Ответ №1:
Вам нужна типизированная запись, чтобы видеть имена столбцов. Для этого вам необходимо создать правильный возвращаемый тип:
create type function_result as
(
event_type text,
start_time TIMESTAMP,
end_time TIMESTAMP,
difference bigint
);
Затем в вашей функции используйте:
return (event_typo,start_tim,end_tim,tim_diff)::function_resu<
( ret
переменная не нужна)
Затем вы можете развернуть запись в запросе на столбцы, используя:
SELECT bank_id, (myfunction(document_id,'DF')).*
FROM timeline_chronicle
WHERE document_id = 102;
Обратите внимание, что:
tim_diff := (select extract(epoch from (end_tim-start_tim)));
может быть упрощен до:
tim_diff := extract(epoch from (end_tim-start_tim));