我有一个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
,这会导致问题。
如何减去变量中包含的日期?
答案 0 :(得分:11)
您的功能正在做什么很多更简单。语法错误的实际原因如下:
SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
看起来您正在尝试将startDate
投射到timestamp
,这一开始是无意义的,因为您的参数startDate
已经被声明为timestamp
。
它也不起作用。我引用the manual here:
为避免语法歧义,类型'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函数:
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 = $1
AND e.evt_id = $2
$func$;
呼叫:
SELECT f_date_diff(5, 6);
如果你坚持使用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$;
同一个电话。
答案 1 :(得分:1)
我会写这样的查询:
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。具体来说,PostgreSQL文档的第39.5.3节。
答案 2 :(得分:1)
你真的需要这个功能吗?
此查询也可以使用:
SELECT (SELECT evt_start_date::date FROM events WHERE evt_id = 5)
- evt_start_date::date
FROM events WHERE evt_id = 6;