3

X分に最も近い値に丸めるにはどうすればよいですか?

これが私の試みです:

DECLARE
  _stamp ALIAS FOR $1; -- timestamp
  _nearest ALIAS FOR $2; -- minutes (integer)
  _minutes decimal;
  _ret timestamp;
BEGIN
  _ret := date_trunc('minute', _stamp);

  SELECT EXTRACT (minute FROM _ret)::integer INTO _minutes;

 IF (_minutes % _nearest < (_nearest / 2)) THEN
    RETURN _ret + _minutes * interval '1 minute';
  ELSE
    RETURN _ret - _minutes * interval '1 minute';
  END IF;

  RETURN _ret;
END;

例:

SELECT round_to_nearest_minute ('2010-01-01 12:34:56', 15);

戻る必要があります

2010-01-01 12:30:00
4

8 に答える 8

2

ラウンドタイム機能は良さそうです。変更なしで任意の時間単位で機能する別の方法は次のとおりです。

SELECT '1970-01-01'::timestamptz + EXTRACT(epoch FROM now())::integer / 300
            * 300 * interval '1 second';

300 への 2 つの参照は、丸めたい秒数です。たとえば、300 = 5 分です。整数演算を使用することで、切り捨ててからエポックからの秒数を掛けて、丸められた値を求めます。

単純なキャストを使用すると、これは常に切り捨てられますが、必要に応じて丸めを四捨五入に変更できます。

最も近い 15 分に丸めたい場合は、300 の代わりに 900 を使用します。最も近い 1 時間半は 5400 になります。

于 2012-09-10T10:31:32.383 に答える
2

足したり引いたりする代わりに

_minutes * interval '1 minute'

あなたは減算する必要があります

(_minutes % _nearest) * interval '1 minute'

または追加

(_nearest - (_minutes % _nearest)) * interval '1 minute'

于 2010-01-26T02:12:25.970 に答える
2

私の以前の回答に加えて、すべてをまとめて、あなたが求めていることを正確に実行する関数を次に示します。

CREATE FUNCTION date_round(base_date timestamptz, round_interval interval)
    RETURNS timestamptz AS $BODY$
SELECT '1970-01-01'::timestamptz 
    + (EXTRACT(epoch FROM $1)::integer + EXTRACT(epoch FROM $2)::integer / 2)
    / EXTRACT(epoch FROM $2)::integer
    * EXTRACT(epoch FROM $2)::integer * interval '1 second';
$BODY$ LANGUAGE SQL STABLE;

そして、これを呼び出す例を次に示します。

SELECT date_round(now(), '15 minutes');

任意の間隔を指定でき、機能するはずです。コード化されているように、最も近い間隔 (上または下) に丸められます。

代わりに切り捨てたい場合は、 + EXTRACT(epoch FROM $2)::integer / 2).

うまくいけば、これは正しい引数タイプ (整数分ではなく間隔) を受け入れる決定的な答えとして機能します。

于 2012-09-10T10:44:42.497 に答える
1

これも役に立ちます: タイムスタンプを 5 分に丸める関数。タイムスタンプの任意のフィールドとそのフィールドの任意の量で動作するように簡単に変更できます。

round_time 関数

于 2012-02-22T13:16:03.240 に答える
0

単純な SQL ステートメントとして実行でき、CURRENT_TIMESTAMP を TIMESTAMP 値に置き換えます。

SELECT date_trunc('minute', CURRENT_TIMESTAMP::timestamp without time zone)
    + (
    CASE WHEN extract(second from CURRENT_TIMESTAMP ) >= 30
        THEN 1::text
        ELSE 0::text
    END
    || ' minute'

    )::interval ;

最適化は、30 秒追加してから実行するだけdate_trunc()です。これは前から知っていましたが、特に感謝していirc://irc.freenode.net/#postgresqlますStuckMojo

SELECT date_trunc(
    'minute'
    , CURRENT_TIMESTAMP::timestamp without time zone
      + '30 seconds'::interval
);

@stephenを更新してください。技術的に言えば、それは質問が求めているものではありませんが。

CREATE OR REPLACE FUNCTION round_trunc ( in text, in timestamp ) RETURNS timestamp without time zone  AS $$
  SELECT pg_catalog.date_trunc(
      $1
      , $2::timestamp without time zone
        + ('0.5 ' || $1 )::interval
  )
$$ LANGUAGE sql VOLATILE;

ちょっと待って、彼が何を求めているかわかりました。彼は時間の最も近い抽象的なサブユニットに丸めたいと思っています。15分のように、私はここから離れています。

于 2010-01-25T23:37:15.983 に答える
0

これはうまくいくようです:

DECLARE
  _stamp ALIAS FOR $1;
  _nearest ALIAS FOR $2;
  _seconds integer;
  _ret timestamp;
  _minutes decimal;
  _mod decimal;
BEGIN
  _ret := date_trunc('minute', _stamp);

  SELECT EXTRACT (minute FROM _ret)::integer INTO _minutes;

  _mod := _minutes % _nearest;

  IF (_mod > (_nearest / 2)) THEN
    RETURN _ret + (_nearest - _mod) * interval '1 minute';
  ELSE
    RETURN _ret - (_mod) * interval '1 minute';
  END IF;

  RETURN _ret;

END;

スティーブン・デンに感謝します:)

于 2010-01-26T08:32:11.747 に答える
-1

関数を使用しますdate_trunc('src', timestamp [value])

ドキュメントを参照してください: http://www.postgresql.org/docs/9.1/static/functions-datetime.html

于 2012-02-20T12:23:06.297 に答える