Как получить Date_Difference MONTHS, DAYS в ORACLE? - PullRequest
0 голосов
/ 01 марта 2020

Теперь я хочу отобразить месяцы и дни между двумя датами, например: -

start_date       end_date
---------        -------- 
1-10-2020        2-11-2020

expected output 
----------------
MONTH       DAYS 
10          30
11          2

Как получить его в oracle ???

Ответы [ 4 ]

1 голос
/ 01 марта 2020

Вам не нужно генерировать все дни, так как это будет неэффективно; просто используйте рекурсивное условие факторинга подзапроса для итерации за каждый месяц:

WITH months ( start_date, next_date, end_date ) AS (
  SELECT start_date,
         LEAST(
           ADD_MONTHS( TRUNC( start_date, 'MM' ), 1 ),
           CAST( end_date + INTERVAL '1' DAY AS DATE )
         ),
         CAST( end_date + INTERVAL '1' DAY AS DATE )
  FROM   table_name
UNION ALL
  SELECT next_date,
         LEAST( ADD_MONTHS( next_date, 1 ), end_date ),
         end_date
  FROM   months
  WHERE  next_date < end_date
)
SELECT EXTRACT( YEAR FROM start_date ) AS year,
       EXTRACT( MONTH FROM start_date ) AS month,
       next_date - start_date AS days
FROM   months;

Итак, для ваших тестовых данных:

CREATE TABLE table_name ( start_date, end_date ) AS
SELECT DATE '2020-10-01', DATE '2020-11-02' FROM DUAL

Это выводит:

YEAR | MONTH | DAYS
---: | ----: | ---:
2020 |    10 |   31
2020 |    11 |    2

дБ <> скрипка здесь

1 голос
/ 01 марта 2020

Вместо внутреннего перечисления каждый день, вы можете включить все (неполные) месяцы, а затем посмотреть, сколько дней в каждом из них находится в диапазоне:

with cte (start_date, end_date) as (
  select date '2020-10-01', date '2020-11-02' from dual
),
rcte (start_date, end_date, part_month) as (
  select start_date, end_date, trunc(start_date, 'MM')
  from cte
  union all
  select start_date, end_date, part_month + interval '1' month
  from rcte
  where part_month < trunc(end_date, 'MM')
)
select extract(month from part_month) as month_num,
  least(end_date, last_day(part_month))
    - greatest(start_date, part_month)
    + 1 as num_days
from rcte
order by part_month;

дБ <> скрипка , показывающая некоторые из рабочих.

0 голосов
/ 01 марта 2020
WITH tablos AS (
  SELECT '2020-01-01' 'start_date',
         '2021-03-29' 'end_date')
SELECT CAST(DATEDIFF(yy, t.start_date, t.end_date) AS varchar(4)) +' year '+
       CAST(DATEDIFF(mm, DATEADD(yy, DATEDIFF(yy, t.start_date, t.end_date), t.start_date), t.end_date) AS varchar(2)) +' month '+
       CAST(DATEDIFF(dd, DATEADD(mm, DATEDIFF(mm, DATEADD(yy, DATEDIFF(yy, t.start_date, t.end_date), t.start_date), t.end_date), 
       DATEADD(yy, DATEDIFF(yy, t.start_date, t.end_date), t.start_date)), t.end_date) AS varchar(2)) +' day' AS result
FROM tablos 

результат

1 year 2 month 28 day
0 голосов
/ 01 марта 2020

Один из вариантов - создать календарь (между начальной и конечной датой), извлечь месяц (и год для ситуаций, когда эти даты охватывают несколько лет) и подсчитать количество дней в этих месяцах.

SQL> with
  2  test (start_date, end_date) as
  3    (select date '2020-10-01',
  4            date '2020-11-02'
  5     from dual
  6    ),
  7  calendar as
  8    (select start_date + level - 1 datum
  9     from test
 10     connect by level <= end_date - start_date + 1
 11    )
 12  select to_char(datum, 'yyyy.mm') month,
 13         count(*) days
 14  From calendar
 15  group by to_char(datum, 'yyyy.mm')
 16  order by 1;

MONTH         DAYS
------- ----------
2020.10         31
2020.11          2

SQL>

(Кстати, в октябре 31 день, а не 30).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...