Разница в дате PostgreSQL
у меня есть функция PostgreSQL, которая вычисляет разницу дат:
CREATE OR REPLACE FUNCTION testDateDiff () RETURNS int AS $BODY$
DECLARE startDate TIMESTAMP;
DECLARE endDate TIMESTAMP;
DECLARE diffDatePart int ;
BEGIN
Select evt_start_date From events Where evt_id = 5 INTO startDate ;
Select evt_start_date From events Where evt_id = 6 INTO endDate ;
SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
RETURN diffDatePart;
END;
$BODY$
LANGUAGE plpgsql
COST 100
Если даты вычитаются непосредственно, то рассчитывается разница. Но в моем случае даты присутствуют в переменных как startDate
и endDate
, который вызывает проблему.
как вычесть даты, содержащиеся в переменных?
3 ответов
Debug
что делает ваша функция может быть сделано много проще. Фактическая причина синтаксической ошибки здесь:
SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
похоже, вы пытаетесь бросить startDate
to timestamp
, что является нонсенсом, потому что ваш параметр startDate
объявлен timestamp
уже.
он также не работает. Цитирую инструкция тут:
чтобы избежать синтаксической двусмысленности синтаксис типа' string ' может быть только используется для указания типа простой литеральной константы.
это б работы такой:
SELECT EXTRACT(day FROM startDate - endDate)::int INTO diffDatePart;
но это все равно не имело бы большого смысла. Вы говорите о "датах", но все же определяете свои параметры как timestamp
. Вы мог бы санируйте то, что у вас есть, вот так:
CREATE OR REPLACE FUNCTION f_date_diff()
RETURNS int AS
$BODY$
DECLARE
start_date date;
end_date date;
date_diff int;
BEGIN
SELECT evt_start_date FROM events WHERE evt_id = 5 INTO start_date;
SELECT evt_start_date FROM events WHERE evt_id = 6 INTO end_date;
date_diff := (endDate - startDate);
RETURN date_diff;
END
$BODY$ LANGUAGE plpgsql;
-
DECLARE
нужно только один раз. -
date
столбцы, объявленные как правильный типdate
. - не используйте идентификаторы смешанных регистров, если вы точно не знаете, что делаете.
- вычесть старт С конец чтобы получить положительное число или применить оператор абсолютного значения
@
. -
после вычитания времени (в отличие от вычитая метки, которые дает
interval
) уже даетinteger
, упростить кому:SELECT (startDate - endDate) INTO diffDatePart;
или даже проще, как назначение plpgsql:
diffDatePart := (startDate - endDate);
простой запрос
вы можете решить простую задачу с помощью простого запроса с помощью подзапроса:
SELECT (SELECT evt_start_date
FROM events
WHERE evt_id = 6)
- evt_start_date AS date_diff
FROM events
WHERE evt_id = 5;
вы можете CROSS JOIN
базовая таблица для себя (1 строка из каждого экземпляра, так что все в порядке):
SELECT e.evt_start_date - s.evt_start_date AS date_diff
FROM events e
,events s
WHERE e.evt_id = 6
AND s.evt_id = 5;
функция SQL
если вы настаиваете на функции для этой цели, используйте простой sql функция:
CREATE OR REPLACE FUNCTION f_date_diff(_start_id int, _end_id int)
RETURNS int LANGUAGE sql AS
$func$
SELECT e.evt_start_date - s.evt_start_date
FROM events s, events e
WHERE s.evt_id =
AND e.evt_id =
$func$;
звоните:
SELECT f_date_diff(5, 6);
функция PL/pgSQL
если вы настаиваете на plpgsql ...
CREATE OR REPLACE FUNCTION f_date_diff(_start_id int, _end_id int)
RETURNS int LANGUAGE plpgsql AS
$func$
BEGIN
RETURN (SELECT evt_start_date
- (SELECT evt_start_date FROM events WHERE evt_id = _start_id)
FROM events WHERE evt_id = _end_id);
END
$func$;
тот же вызов.
Я бы написал запрос следующим образом:
create function testDateDiff()
returns integer as $$
declare
startDate timestamp;
endDate timestamp;
begin
startDate := (select evt_start_date From events Where evt_id = 5);
endDate := (select evt_start_date From events Where evt_id = 6);
return (select extract(day from startDate - endDate));
end;
$$ language 'plpgsql';
разница между использованием :=
и into
в контексте выше это использование :=
запрос должен возвращать одно значение. Если вы используете into
запрос может возвращать одну строку (т. е. более одного столбца).
для полного объяснения с помощью select
С into
и plpgsql вы должны прочитать http://www.postgresql.org/docs/9.1/static/plpgsql-statements.html. В частности, раздел 39.5.3 документации PostgreSQL.
вам действительно нужна функция для этого?
этот запрос также будет работать:
SELECT (SELECT evt_start_date::date FROM events WHERE evt_id = 5)
- evt_start_date::date
FROM events WHERE evt_id = 6;