如何在PostgreSQL中计算日期差异?

80

我需要在PostgreSQL中计算两个日期之间的差异。

在SQL Server中,就像我们在SQL Server中所做的那样,这要容易得多。

DATEDIFF(Day, MIN(joindate), MAX(joindate)) AS DateDifference;

我的尝试:我正在尝试使用以下脚本:

(Max(joindate) - Min(joindate)) as DateDifference;

问题

  • 我的方法正确吗?

  • PostgreSQL 中是否有计算此功能的函数?

6个回答

89

你对于 DATE 类型的计算是正确的,但如果你的值是时间戳,你可能应该使用 EXTRACT (或者 DATE_PART) 来确保只获取 完整 天数的差异;

EXTRACT(DAY FROM MAX(joindate)-MIN(joindate)) AS DateDifference

一个用于测试的SQLfiddle。请注意时间戳差异比两个完整天少1秒。


2
@JurajPetrik 嗯,SELECT EXTRACT(DAY FROM TO_TIMESTAMP('2016-01-01', 'YYYY-MM-DD')-TO_TIMESTAMP('2015-03-01', 'YYYY-MM-DD')); 给出了306天,这似乎是正确的(大于31天)。 - Joachim Isaksson

22

一个简单的方法是将日期转换为时间戳,计算它们之间的差异,然后提取DAY部分。

如果您想要真正的差异

select extract(day from 'DATE_A'::timestamp - 'DATE_B'::timestamp);

如果您想要绝对差异

select abs(extract(day from 'DATE_A'::timestamp - 'DATE_B'::timestamp));

7
可能这个问题很老,所以可能在过去无法解决,但现在你可以使用 select date_x - date_y as thing 来实现。请注意,我会尽力让翻译更通俗易懂,但不会改变原意。 - coladict
1
这里有一个警告。这仅从时间段中提取天数部分。A) 3天23小时仍将导致3,B)extract(hour from ...) 3天和23小时将导致23而不是95,C)月份和年份始终为0。 - jakob-r

18

将两个字段都转换为日期数据类型,然后您就可以使用减号:

(CAST(MAX(joindate) AS date) - CAST(MIN(joindate) AS date)) as DateDifference

测试用例:

SELECT  (CAST(MAX(joindate) AS date) - CAST(MIN(joindate) AS date)) as DateDifference
FROM 
    generate_series('2014-01-01'::timestamp, '2014-02-01'::timestamp, interval '1 hour') g(joindate);

结果: 31

或者创建一个名为datediff()的函数:

CREATE OR REPLACE FUNCTION datediff(timestamp, timestamp) 
RETURNS int 
LANGUAGE sql 
AS
$$
    SELECT CAST($1 AS date) - CAST($2 AS date) as DateDifference
$$;

创建函数后,我只需要使用 datediff(joindate,joindate) 对吗? - Sarfaraz Makandar
在 SQL 查询中,它本身不起作用(只是为未来的读者添加这个)。 - Vasspilka

14

这是我通常的做法。B减去A的天数差。

DATE_PART('day', MAX(joindate) - MIN(joindate)) as date_diff

1
我认为如果两个日期不是来自同一个月份,这可能会生成负日期。 - igorkf

7

这不是对OP问题的直接回答,但当我的搜索带我来到这个主题时,这就是我正在寻找的答案。

对于想要创建一个表示两个日期之间差异的易于理解的字符串的人,考虑使用AGE()函数。

 AGE(table.end_date, table.start_date)

它产生的结果看起来像这样:

0:00:27

3 days 22:06:39.833264
4 days 01:12:39.473559
20 days 17:53:20.23287
23 days 21:01:15.150703

1 mon 19 days 01:52:24.262275
2 mons 17 days 05:04:12.277099
2 mons 17 days 04:59:21.618069

1
如果您已经有了时间戳,那么您就不需要进行任何转换。对于绝对差异,@zubair-0的答案非常好,以下是实现方法...
select abs(extract(day from A - B)) from table_name;

注意:A和B是时间戳数据类型


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接