Получите разницу между двумя датами как в месяцах, так и в днях в sql
Мне нужно получить разницу между двумя датами, если разница составляет 84 дня, я должен, вероятно, иметь выход как 2 месяца и 14 дней, код, который я только что давал, составляет всего. Вот код
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 дней.
Ответы
Ответ 1
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
Ответ 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
дням, когда Oracle рассматривает 31
дни в месяц (как в марте, так и в апреле).
Ответ 3
Я думаю, что ваш вопрос не определен достаточно хорошо по следующей причине.
Ответы, полагающиеся на months_between, должны иметь дело со следующей проблемой: функция сообщает ровно один месяц между 2013-02-28 и 2013-03-31, а также между 2013-01-28 и 2013-02-28 и между 2013-01-31 и 2013-02-28 (я подозреваю, что некоторые ответчики не использовали эти функции на практике или сейчас придется пересмотреть производственный код!)
Это документированное поведение, в котором даты, которые являются последними в соответствующие месяцы или которые относятся к одному и тому же дню месяца, оцениваются как целое число месяцев.
Итак, вы получаете тот же результат "1" при сравнении 2013-02-28 с 2013-01-28 или с 2013-01-31, но сравнивая его с 2013-01-29 или 2013-01-30 дает 0.967741935484 и 0.935483870968 соответственно - так, как одна точка приближается к другой, разница, сообщаемая этой функцией, может увеличиться.
Если это не приемлемая ситуация, вам придется написать более сложную функцию или просто полагаться на расчет, который предполагает 30 (например) дней в месяц. В последнем случае, как вы будете работать с 2013-02-28 и 2013-03-31?
Ответ 4
это то, что вы имеете?
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;
Ответ 5
Здесь я просто делаю разницу между сегодняшним днем и CREATED_DATE
DATE
в таблице, которая, очевидно, является датой в прошлом:
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
Я использую (365/12), или 30.416667, как свой коэффициент перевода, потому что я использую общие дни и удаляю годы и месяцы (как дни), чтобы получить оставшееся количество дней. Во всяком случае, это было достаточно хорошо для моих целей.
Ответ 6
Решение, которое я опубликую, рассмотрит месяц с 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);
Ответ 7
Синтаксис MsSql: DATEDIFF (datepart, startdate, enddate)
Oracle: это вернет число дней
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
Ответ 8
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
Ответ 9
Узнать год - Месяц-День между двумя днями в Орале 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;
Ответ 10
См. запрос ниже (предполагается @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).