PostgreSQL
 sql >> Datenbank >  >> RDS >> PostgreSQL

PostgreSQL-Datumsunterschied

Debuggen

Was Ihre Funktion tut, könnte viel tun einfacher. Die eigentliche Ursache für den Syntaxfehler ist hier:

SELECT EXTRACT(day FROM TIMESTAMP startDate - endDate) INTO diffDatePart;

Es sieht so aus, als ob Sie versuchen, startDate zu casten zu timestamp , was zunächst Unsinn ist, weil Ihr Parameter startDate wird als timestamp deklariert schon.

Es funktioniert auch nicht. Ich zitiere das Handbuch hier :

Es würde funktioniert so:

SELECT EXTRACT(day FROM startDate - endDate)::int INTO diffDatePart;

Aber das würde noch nicht viel Sinn machen. Sie sprechen von "Daten", definieren Ihre Parameter aber immer noch als timestamp . Sie könnten säubern Sie, was Sie haben, wie folgt:

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 nur einmal benötigt.
  • date Spalten, die als richtiger Typ date deklariert sind .
  • Verwenden Sie keine Groß-/Kleinschreibung, es sei denn, Sie wissen genau, was Sie tun.
  • Subtrahieren Sie den Start vom Ende um eine positive Zahl zu erhalten, oder wenden Sie den Absolutwertoperator @ .
  • Seit dem Subtrahieren von Daten (im Gegensatz zum Subtrahieren von Zeitstempeln , was ein interval ergibt ) ergibt bereits integer , vereinfachen zu:

    SELECT (startDate - endDate) INTO diffDatePart;
    

    Oder noch einfacher als plpgsql-Zuweisung:

    diffDatePart := (startDate - endDate);
    

Einfache Abfrage

Sie können die einfache Aufgabe mit einer einfachen Abfrage lösen - mit einer Unterabfrage:

SELECT (SELECT evt_start_date
        FROM   events
        WHERE  evt_id = 6) 
      - evt_start_date AS date_diff
FROM   events
WHERE  evt_id = 5;

Oder Sie könnten CROSS JOIN die Basistabelle für sich selbst (1 Zeile von jeder Instanz, also ist das in Ordnung):

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-Funktion

Wenn Sie zu diesem Zweck auf einer Funktion bestehen, verwenden Sie eine einfache SQL-Funktion:

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$;

Aufruf:

SELECT  f_date_diff(5, 6);

PL/pgSQL-Funktion

Wenn Sie auf plpgsql bestehen ...

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$;

Gleicher Aufruf.