9

日付の差を計算する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

日付を直接引くと、差が計算されます。しかし、私の場合、日付は変数asstartDateendDateに存在するため、問題が発生します。

変数に含まれる日付を減算するにはどうすればよいですか?

4

3 に答える 3

11

デバッグ

関数が実行していることは、はるかに簡単に実行できます。構文エラーの実際の原因は次のとおりです。

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

パラメータがすでに宣言されているため、にキャストしよstartDateうとしているように見えますが、最初は意味がありません。timestampstartDatetimestamp

また、動作しません。ここでマニュアルを引用します:

構文のあいまいさを回避するために、タイプ'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 = $1
AND    e.evt_id = $2
$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$;

同じ呼び出し。

于 2012-12-30T15:40:34.587 に答える
1

これには本当に関数が必要ですか?

このクエリも同様に機能します。

SELECT (SELECT evt_start_date::date FROM events WHERE evt_id = 5) 
        - evt_start_date::date 
        FROM events WHERE evt_id = 6;
于 2012-12-31T05:06:10.707 に答える
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

selectwithintoおよび plpgsqlの使用に関する完全な説明については、http://www.postgresql.org/docs/9.1/static/plpgsql-statements.htmlを参照してください。具体的には、PostgreSQL ドキュメントのセクション 39.5.3 です。

于 2012-12-29T00:09:59.730 に答える