PostgreSQL日期差异

Sat*_*rma 9 sql postgresql datetime plpgsql postgresql-9.1

我有一个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
Run Code Online (Sandbox Code Playgroud)

如果直接减去日期,则计算差异.但在我的情况下,日期存在于变量as startDateendDate,这会导致问题.

如何减去变量中包含的日期?

Erw*_*ter 11

调试

你的功能可以做得简单.语法错误的实际原因如下:

SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;
Run Code Online (Sandbox Code Playgroud)

它看起来像你正在尝试强制startDate转换timestamp,这一开始是无稽之谈,因为你的参数startDate已经声明timestamp.

它也行不通.我在这里引用手册:

为避免语法歧义,类型'string'语法只能用于指定简单文字常量的类型.

像这样工作:

SELECT EXTRACT(day FROM startDate - endDate)::int INTO diffDatePart;
Run Code Online (Sandbox Code Playgroud)

但这仍然没有多大意义.您正在谈论"日期",但仍将您的参数定义为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;
Run Code Online (Sandbox Code Playgroud)
  • DECLARE 只需要一次.
  • date声明为正确类型的列date.
  • 除非您确切知道自己在做什么,否则请勿使用大小写混合标识符.
  • 结尾减去开头以获得正数或应用绝对值运算符.@
  • 由于减去日期(而不是减去产生时间的时间戳interval)已经产生integer,因此简化为:

    SELECT (startDate - endDate) INTO diffDatePart;
    
    Run Code Online (Sandbox Code Playgroud)

    或者更简单的plpgsql赋值:

    diffDatePart := (startDate - endDate);
    
    Run Code Online (Sandbox Code Playgroud)

简单的查询

您可以使用简单查询解决简单任务 - 使用子查询:

SELECT (SELECT evt_start_date
        FROM   events
        WHERE  evt_id = 6) 
      - evt_start_date AS date_diff
FROM   events
WHERE  evt_id = 5;
Run Code Online (Sandbox Code Playgroud)

或者您可以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;
Run Code Online (Sandbox Code Playgroud)

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 = $1
AND    e.evt_id = $2
$func$;
Run Code Online (Sandbox Code Playgroud)

呼叫:

SELECT  f_date_diff(5, 6);
Run Code Online (Sandbox Code Playgroud)

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$;
Run Code Online (Sandbox Code Playgroud)

同样的电话.