2012-07-16 91 views
13

我需要得到两个日期之间的差异说如果差异是84天,我应该可能有2个月和14天的输出,我只是代码给出总数。下面是代码获取两个日期在两个日期之间的差异在几个月和几天在sql

SELECT Months_between(To_date('20120325', 'YYYYMMDD'), 
     To_date('20120101', 'YYYYMMDD')) 
     num_months, 
     (To_date('20120325', 'YYYYMMDD') - To_date('20120101', 'YYYYMMDD')) 
     diff_in_days 
FROM dual; 

输出是:

NUM_MONTHS DIFF_IN_DAYS 
2.774193548  84 

我需要例如输出此查询是2个月,14天最坏的,否则我也不会介意,如果我能有几个月后的确切日期,因为那些日子不是真的14,因为所有的月份都没有30天。

+0

是否没有人回答这个问题? – ErrorNotFoundException 2012-11-01 10:07:08

+2

不应该是2个月和24天吗? – Noel 2013-08-14 00:38:07

回答

17
select 
    dt1, dt2, 
    trunc(months_between(dt2,dt1)) mths, 
    dt2 - add_months(dt1, trunc(months_between(dt2,dt1))) days 
from 
(
    select date '2012-01-01' dt1, date '2012-03-25' dt2 from dual union all 
    select date '2012-01-01' dt1, date '2013-01-01' dt2 from dual union all 
    select date '2012-01-01' dt1, date '2012-01-01' dt2 from dual union all 
    select date '2012-02-28' dt1, date '2012-03-01' dt2 from dual union all 
    select date '2013-02-28' dt1, date '2013-03-01' dt2 from dual union all 
    select date '2013-02-28' dt1, date '2013-04-01' dt2 from dual union all 
    select trunc(sysdate-1) dt1, sysdate    from dual 
) sample_data 

个结果:

|      DT1 |      DT2 | MTHS |  DAYS | 
---------------------------------------------------------------------------- 
| January, 01 2012 00:00:00 | March, 25 2012 00:00:00 | 2 |  24 | 
| January, 01 2012 00:00:00 | January, 01 2013 00:00:00 | 12 |  0 | 
| January, 01 2012 00:00:00 | January, 01 2012 00:00:00 | 0 |  0 | 
| February, 28 2012 00:00:00 | March, 01 2012 00:00:00 | 0 |  2 | 
| February, 28 2013 00:00:00 | March, 01 2013 00:00:00 | 0 |  1 | 
| February, 28 2013 00:00:00 | April, 01 2013 00:00:00 | 1 |  1 | 
| August, 14 2013 00:00:00 | August, 15 2013 05:47:26 | 0 | 1.241273 | 

链接到测试:SQLFiddle

+0

请问dt2和dt1代表什么我认为我有些约会? – ErrorNotFoundException 2013-08-14 05:41:18

+1

希望您不介意我向查询中添加了一些示例数据。没有其他答案能够产生准确的结果。大多数甚至不是很接近。这是2月28日左右的结果,真正显示出差异。假设每月30或31天不会总是有效。我不确定是否有用于计算月份和日期的官方算法,但这些结果对我来说是最好的。 – 2013-08-15 05:29:16

+0

@Stanley我加入了'jonearles'并为闰年和日期添加了两个更多的例子,加上链接到任何人都可以在线测试解决方案的网站。 – ThinkJet 2013-08-15 06:07:28

-2

MSSQL语法: DATEDIFF(日期部分,开始日期,结束日期)

甲骨文:这将返回天数

select 
    round(Second_date - First_date) as Diff_InDays,round ((Second_date - First_date)/(30),1) as Diff_InMonths,round ((Second_date - First_date) * (60*24),2) as TimeIn_Minitues 
from 
    (
    select 
    to_date('01/01/2012 01:30:00 PM','mm/dd/yyyy hh:mi:ss am') as First_date 
    ,to_date('05/02/2012 01:35:00 PM','mm/dd/yyyy HH:MI:SS AM') as Second_date 
    from 
    dual 
) result; 

演示:http://sqlfiddle.com/#!4/c26e8/36

+0

这是一个transact sql语法,而不是oracle – Oofpez 2012-07-16 07:53:57

+0

即使在tsql中不会给OP要求 – Madhivanan 2012-07-16 07:54:37

+0

上午在使用Oracle和Talend Open Studio – ErrorNotFoundException 2012-07-16 07:55:27

-2
SELECT (MONTHS_BETWEEN(date2,date1) + (datediff(day,date2,date1))/30) as num_months, 
datediff(day,date2,date1) as diff_in_days FROM dual; 

// You should replace date2 with TO_DATE('2012/03/25', 'YYYY/MM/DD') 
// You should replace date1 with TO_DATE('2012/01/01', 'YYYY/MM/DD') 
// To get you results 
+0

DateDiff是在什么Oracle表中,因为它在双重>返回Invaid标识符? – ErrorNotFoundException 2012-07-16 10:46:47

+0

是的。你是对的我会尽快为你提供oracle的具体解决方案 – Sami 2012-07-16 11:49:22

+0

如果datediff不适合你只是简单地尝试date2-date1而不是datediff(day,date2,date1) 无论工作与我分享请谢谢 – Sami 2012-07-16 12:28:20

-4

见下面的查询(假定@ DT1> = @ DT2);

Declare @dt1 datetime = '2013-7-3' 
Declare @dt2 datetime = '2013-5-2' 

select abs(DATEDIFF(DD, @dt2, @dt1)) Days, 
case when @dt1 >= @dt2 
    then case when DAY(@dt2)<=DAY(@dt1) 
     then Convert(varchar, DATEDIFF(MONTH, @dt2, @dt1)) + CONVERT(varchar, ' Month(s) ') + Convert(varchar, DAY(@dt1)-DAY(@dt2)) + CONVERT(varchar, 'Day(s).') 
     else Convert(varchar, DATEDIFF(MONTH, @dt2, @dt1)-1) + CONVERT(varchar, ' Month(s) ') + convert(varchar, abs(DATEDIFF(DD, @dt1, DateAdd(Month, -1, @dt1))) - (DAY(@dt2)-DAY(@dt1))) + CONVERT(varchar, 'Day(s).') 
    end 
    else 'See asumption: @dt1 must be >= @dt2' 
end In_Months_Days 

返回:

Days | In_Months_Days 

62 | 2 Month(s) 1Day(s). 
+1

Oracle的问题,而不是一个SQL Server的问题。 – 2013-08-13 21:27:30

2

更新的正确性。最初由@jen回答。

with DATES as (
    select TO_DATE('20120101', 'YYYYMMDD') as Date1, 
      TO_DATE('20120325', 'YYYYMMDD') as Date2 
    from DUAL union all 
    select TO_DATE('20120101', 'YYYYMMDD') as Date1, 
      TO_DATE('20130101', 'YYYYMMDD') as Date2 
    from DUAL union all 
    select TO_DATE('20120101', 'YYYYMMDD') as Date1, 
      TO_DATE('20120101', 'YYYYMMDD') as Date2 
    from DUAL union all 
    select TO_DATE('20130228', 'YYYYMMDD') as Date1, 
      TO_DATE('20130301', 'YYYYMMDD') as Date2 
    from DUAL union all 
    select TO_DATE('20130228', 'YYYYMMDD') as Date1, 
      TO_DATE('20130401', 'YYYYMMDD') as Date2 
    from DUAL 
), MONTHS_BTW as (
    select Date1, Date2, 
      MONTHS_BETWEEN(Date2, Date1) as NumOfMonths 
    from DATES 
) 
select TO_CHAR(Date1, 'MON DD YYYY') as Date_1, 
     TO_CHAR(Date2, 'MON DD YYYY') as Date_2, 
     NumOfMonths as Num_Of_Months, 
     TRUNC(NumOfMonths) as "Month(s)", 
     ADD_MONTHS(Date2, - TRUNC(NumOfMonths)) - Date1 as "Day(s)" 
from MONTHS_BTW; 

SQLFiddle演示:

 
    +--------------+--------------+-----------------+-----------+--------+ 
    | DATE_1  | DATE_2  | NUM_OF_MONTHS | MONTH(S) | DAY(S) | 
    +--------------+--------------+-----------------+-----------+--------+ 
    | JAN 01 2012 | MAR 25 2012 | 2.774193548387 |  2 |  24 | 
    | JAN 01 2012 | JAN 01 2013 | 12    |  12 |  0 | 
    | JAN 01 2012 | JAN 01 2012 | 0    |  0 |  0 | 
    | FEB 28 2013 | MAR 01 2013 | 0.129032258065 |  0 |  1 | 
    | FEB 28 2013 | APR 01 2013 | 1.129032258065 |  1 |  1 | 
    +--------------+--------------+-----------------+-----------+--------+ 

注意,如何在过去的两个日期,Oracle报表月份的小数部分(这使天)不正确。 0.1290恰好对应于4天,甲骨文考虑在一个月内(3月和4月)考虑31天。

+0

不是很准确。它应该已经返回了24天。 – Noel 2013-08-14 11:32:46

+0

@ Ramblin'Man感谢您的高抬头。显然,使用31作为“一个月内的日子”似乎已经修复了它。我实际上认为30和31有时候会返回确切的时间,有时候会关闭1天(取决于选择几个月),但是,这一轮会照顾它。如果你喜欢,再看看。 – 2013-08-14 12:53:43

+2

乘以30或31并不是一个好主意。它会在某些日期中断,尤其是在涉及二月的时候。 – Noel 2013-08-15 05:32:11

0

我后一个月就会考虑30天

select CONCAT (CONCAT (num_months,' MONTHS '), CONCAT ((days-(num_months)*30),' DAYS ')) 
    from ( 
    SELECT floor(Months_between(To_date('20120325', 'YYYYMMDD'), 
    To_date('20120101', 'YYYYMMDD'))) 
    num_months, 
    (To_date('20120325', 'YYYYMMDD') - To_date('20120101', 'YYYYMMDD')) 
    days 
    FROM dual); 
+3

乘以30或31并不是一个好主意。它会在某些日期中断,尤其是在涉及二月的时候。 – Noel 2013-08-15 05:32:51

+0

我乘以'(365/12)'或'30.41667',但使用的方式不是直接找到使用该结果数字的实际日期,如上所述。您可以使用它来将MONTHS_BETWEEN'转换为天数,从而得出总天数,然后减去数月的时间(以天为单位),以查找实际的剩余天数。 – vapcguy 2016-12-06 15:32:16

1

的解决方案是这是你所换货?

select trunc(months_between(To_date('20120325', 'YYYYMMDD'),to_date('20120101','YYYYMMDD'))) months, 
      round(To_date('20120325', 'YYYYMMDD')-add_months(to_date('20120101','YYYYMMDD'), 
          trunc(months_between(To_date('20120325', 'YYYYMMDD'),to_date('20120101','YYYYMMDD'))))) days 
     from dual; 
+0

如20120129 - 20120325这样的日期将不起作用。 – Noel 2013-08-15 05:03:34

+0

谢谢,现在是:) – planben 2013-08-15 05:23:56

+0

这也是正确的:P – ErrorNotFoundException 2013-08-15 08:52:42

2

我认为这是没有定义你的问题不够好,原因如下。

依靠months_between的答案必须处理以下问题:函数报告2013-02-28和2013-03-31之间以及2013-01-28和2013-02-28之间的一个月,以及2013-01-31和2013-02-28之间(我怀疑有些回答者在实践中没有使用这些功能,或者现在要去检查一些生产代码!)

这是有记录的行为,其中分别是各自月份的最后一个日期或落在当月的同一天的日期被判断为相隔几个月的整数。

因此,比较2013-02-28与2013-01-28或2013-01-31时得到的结果是“1”,但与2013-01-29或2013-01- 30分别给出了0.967741935484和0.935483870968 - 因此当一个日期接近另一个时,由该函数报告的差异可以增加。

如果这不是一个可接受的情况,那么你将不得不写一个更复杂的函数,或者只是依靠一个假设每月30(例如)天的计算。在后一种情况下,你将如何处理2013-02-28和2013-03-31?

+1

您提出了一些优秀的观点。这是一个没有完美答案的简单常见问题。无论使用哪种解决方案,都应该包含免责声明。我仍然会把赏金奖给公认的答案,因为它对我来说很合适。但那可能只是因为我太多地使用了'months_between'。 – 2013-08-16 19:21:34

+0

是的,正如Jon Heller所说的,2-28到3-31是'1'而不是2-28到3-28 ='1'的好处。这就是为什么当你想到几天的时候,你应该真正数天,而不是“MONTHS_BETWEEN”。 – vapcguy 2016-12-06 14:49:58

-2

找出年 - 在ORALE的Sql月 - 日两天之间


select 
trunc(trunc(months_between(To_date('20120101', 'YYYYMMDD'),to_date('19910228','YYYYMMDD')))/12) years , 
trunc(months_between(To_date('20120101', 'YYYYMMDD'),to_date('19910228','YYYYMMDD'))) 
- 
(trunc(trunc(months_between(To_date('20120101', 'YYYYMMDD'),to_date('19910228','YYYYMMDD')))/12))*12 
months, 
      round(To_date('20120101', 'YYYYMMDD')-add_months(to_date('19910228','YYYYMMDD'), 
          trunc(months_between(To_date('20120101', 'YYYYMMDD'),to_date('19910228','YYYYMMDD'))))) days 
     from dual; 
1

在这里,我只是在做今天的区别,并在表中的CREATED_DATEDATE场,这显然是在过去的某个日期:

SELECT 
((FLOOR(ABS(MONTHS_BETWEEN(CREATED_DATE, SYSDATE)))/12) * 12) || ' months, ' AS MONTHS, 
-- we take total days - years(as days) - months(as days) to get remaining days 
FLOOR((SYSDATE - CREATED_DATE) -  -- total days 
(FLOOR((SYSDATE - CREATED_DATE)/365)*12)*(365/12) -  -- years, as days 
-- this is total months - years (as months), to get number of months, 
-- then multiplied by 30.416667 to get months as days (and remove it from total days) 
FLOOR(((SYSDATE - CREATED_DATE)/365)*12 - (FLOOR((SYSDATE - CREATED_DATE)/365)*12)) * (365/12)) 
|| ' days ' AS DAYS 
FROM MyTable 

我使用(一十二分之三百六十五),或30.416667,我的换算系数,因为我使用的总天数和删除年和月(如昼s)来获得剩余天数。无论如何,这对我的目的来说已经足够了。