PostgreSQLで SQLServer-function datediff を実装する方法を探しています。あれは、
この関数は、指定されたstartdateとenddateの間で交差した指定されたdatepart境界のカウントを(符号付き整数値として)返します。
datediff(dd, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
datediff(mm, '2010-04-01', '2012-03-05') = 23 // 23 changes of month
datediff(yy, '2010-04-01', '2012-03-05') = 2 // 2 changes of year
私は単に減算を使用して「dd」を実行できることを知っていますが、他の2つについてのアイデアはありますか?
次のようなものを試してください:
select age('2010-04-01', '2012-03-05'),
date_part('year',age('2010-04-01', '2012-03-05')),
date_part('month',age('2010-04-01', '2012-03-05')),
date_part('day',age('2010-04-01', '2012-03-05'));
この関数は、2つの日付の間の年、月、日...fullを提供します。日付の変更数については、revouaが提供するリンクを使用してください。 http://www.sqlines.com/postgresql/how-to/datediff
単純にそれらを引きます:
select '2015-01-12'::date - '2015-01-01'::date;
これにより、以下が得られます。
?column?
----------
11
最良の答えを探すのにしばらく時間を費やしましたが、私はそれを持っていると思います。
このSQLは、2つの日付間の日数をinteger
として提供します。
SELECT
(EXTRACT(Epoch from age('2017-6-15', now())) / 86400)::int
..今日実行すると(2017-3-28
)、以下が提供されます。
?column?
------------
77
受け入れられた答えについての誤解:
select age('2010-04-01', '2012-03-05'),
date_part('year',age('2010-04-01', '2012-03-05')),
date_part('month',age('2010-04-01', '2012-03-05')),
date_part('day',age('2010-04-01', '2012-03-05'));
..は、2つの日付間の時間ではなく、日付文字列の部分間のリテラルの違いを取得するということです。
I.E:
Age(interval)=-1 years -11 mons -4 days;
Years(double precision)=-1;
Months(double precision)=-11;
Days(double precision)=-4;
必要な機能とほぼ同じ(atiruzの回答、 here のUDFの短縮バージョンに基づく)
CREATE OR REPLACE FUNCTION datediff(type VARCHAR, date_from DATE, date_to DATE) RETURNS INTEGER LANGUAGE plpgsql
AS
$$
DECLARE age INTERVAL;
BEGIN
CASE type
WHEN 'year' THEN
RETURN date_part('year', date_to) - date_part('year', date_from);
WHEN 'month' THEN
age := age(date_to, date_from);
RETURN date_part('year', age) * 12 + date_part('month', age);
ELSE
RETURN (date_to - date_from)::int;
END CASE;
END;
$$;
使用法:
/* Get months count between two dates */
SELECT datediff('month', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 10 */
/* Get years count between two dates */
SELECT datediff('year', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 1 */
/* Get days count between two dates */
SELECT datediff('day', '2015-02-14'::date, '2016-01-03'::date);
/* Result: 323 */
/* Get months count between specified and current date */
SELECT datediff('month', '2015-02-14'::date, NOW()::date);
/* Result: 47 */
SELECT date_part ('year', f) * 12
+ date_part ('month', f)
FROM age ('2015-06-12'::DATE, '2014-12-01'::DATE) f
結果:6
Riki_tiki_taviの答えを拡張して、データを公開したいと思います。 SQLサーバーが実行するほとんどすべてを実行するdatediff関数を作成しました。そのようにして、任意のユニットを考慮することができます。
create function datediff(units character varying, start_t timestamp without time zone, end_t timestamp without time zone) returns integer
language plpgsql
as
$$
DECLARE
diff_interval INTERVAL;
diff INT = 0;
years_diff INT = 0;
BEGIN
IF units IN ('yy', 'yyyy', 'year', 'mm', 'm', 'month') THEN
years_diff = DATE_PART('year', end_t) - DATE_PART('year', start_t);
IF units IN ('yy', 'yyyy', 'year') THEN
-- SQL Server does not count full years passed (only difference between year parts)
RETURN years_diff;
ELSE
-- If end month is less than start month it will subtracted
RETURN years_diff * 12 + (DATE_PART('month', end_t) - DATE_PART('month', start_t));
END IF;
END IF;
-- Minus operator returns interval 'DDD days HH:MI:SS'
diff_interval = end_t - start_t;
diff = diff + DATE_PART('day', diff_interval);
IF units IN ('wk', 'ww', 'week') THEN
diff = diff/7;
RETURN diff;
END IF;
IF units IN ('dd', 'd', 'day') THEN
RETURN diff;
END IF;
diff = diff * 24 + DATE_PART('hour', diff_interval);
IF units IN ('hh', 'hour') THEN
RETURN diff;
END IF;
diff = diff * 60 + DATE_PART('minute', diff_interval);
IF units IN ('mi', 'n', 'minute') THEN
RETURN diff;
END IF;
diff = diff * 60 + DATE_PART('second', diff_interval);
RETURN diff;
END;
$$;
出力を含む完全な例を次に示します。 psql(10.1、サーバー9.5.10)。
30未満の値ではなく、58を取得します。
age()関数を削除し、前の投稿で言及した問題を解決しました。
drop table t;
create table t(
d1 date
);
insert into t values(current_date - interval '58 day');
select d1
, current_timestamp - d1::timestamp date_diff
, date_part('day', current_timestamp - d1::timestamp)
from t;
d1 | date_diff | date_part
------------+-------------------------+-----------
2018-05-21 | 58 days 21:41:07.992731 | 58
この質問は誤解に満ちています。最初に質問を完全に理解させます。質問者は、 MS SQL Server関数DATEDIFF ( datepart , startdate , enddate )
を実行したときと同じ結果を得たいと考えています。ここで、datepart
はdd
、mm
、またはyy
を取ります。
この関数は次によって定義されます:
この関数は、指定されたstartdateとenddateの間で交差した指定されたdatepart境界のカウントを(符号付き整数値として)返します。
これは、いくつの日の境界、月の境界、または年の境界が越えられるかを意味します。それらの間には何日、何ヶ月、何年もありません。 datediff(yy, '2010-04-01', '2012-03-05')
が1ではなく2である理由は、これらの日付の間に2年未満があり、1年だけが過ぎたが、2010年から2011年、および2011年から2012年に2年の境界を越えたことを意味します。
以下は、ロジックを正しく複製するための最善の試みです。
-- datediff(dd`, '2010-04-01', '2012-03-05') = 704 // 704 changes of day in this interval
select ('2012-03-05'::date - '2010-04-01'::date );
-- 704 changes of day
-- datediff(mm, '2010-04-01', '2012-03-05') = 23 // 23 changes of month
select (date_part('year', '2012-03-05'::date) - date_part('year', '2010-04-01'::date)) * 12 + date_part('month', '2012-03-05'::date) - date_part('month', '2010-04-01'::date)
-- 23 changes of month
-- datediff(yy, '2010-04-01', '2012-03-05') = 2 // 2 changes of year
select date_part('year', '2012-03-05'::date) - date_part('year', '2010-04-01'::date);
-- 2 changes of year