Диапазон дат окончания месяца, где самый последний день = системная дата - PullRequest
0 голосов
/ 18 февраля 2020

Я пытаюсь сгенерировать диапазон дат «последний день месяца» от заданной даты начала (01/01/2019) до системной даты (sysdate). Я могу сгенерировать диапазон дат для этого, используя следующий запрос:

select last_day(add_months (trunc (to_date('01/01/2019','MM/DD/YYYY'), 'MM'), Level - 1))

Month   FROM Dual

CONNECT BY Level <= MONTHS_BETWEEN(sysdate, to_date('01/01/2019','MM/DD/YYYY')) + 1

order by month

Я пытаюсь получить последнюю запись равной sysdate, чтобы я мог рассчитать текущие остатки - как я могу go о добавить это к вышеуказанному запросу?

Пример вывода решения:

+------------------------+
|         MONTH          |
+------------------------+
| 1/31/2019 12:00:00 AM  |
| 2/28/2019 12:00:00 AM  |
| 3/31/2019 12:00:00 AM  |
| 4/30/2019 12:00:00 AM  |
| 5/31/2019 12:00:00 AM  |
| 6/30/2019 12:00:00 AM  |
| 7/31/2019 12:00:00 AM  |
| 8/31/2019 12:00:00 AM  |
| 9/30/2019 12:00:00 AM  |
| 10/31/2019 12:00:00 AM |
| 11/30/2019 12:00:00 AM |
| 12/31/2019 12:00:00 AM |
| 1/31/2020 12:00:00 AM  |
| 2/25/2020 12:00:00 AM  |
+------------------------+

Ответы [ 2 ]

1 голос
/ 18 февраля 2020

Если я вас правильно понял, вы бы хотели, чтобы сегодняшняя дата была в последней строке. Если это так, используйте CASE (строки # 13 - 19).

Строки # 1 - 12 представляют ваш текущий запрос.

SQL> alter session set nls_date_format = 'dd.mm.yyyy hh24:mi:ss';

Session altered.

SQL> WITH your_data
  2       AS (    SELECT LAST_DAY (
  3                         ADD_MONTHS (
  4                            TRUNC (TO_DATE ('01/01/2019', 'MM/DD/YYYY'), 'MM'),
  5                            LEVEL - 1))
  6                         Month
  7                 FROM DUAL
  8           CONNECT BY LEVEL <=
  9                           MONTHS_BETWEEN (
 10                              SYSDATE,
 11                              TO_DATE ('01/01/2019', 'MM/DD/YYYY'))
 12                         + 1)
 13    SELECT CASE
 14              WHEN TRUNC (month, 'mm') = TRUNC (SYSDATE, 'mm')
 15              THEN
 16                 TRUNC (SYSDATE)
 17              ELSE
 18                 month
 19           END
 20              month
 21      FROM your_data
 22  ORDER BY month;

MONTH
-------------------
31.01.2019 00:00:00
28.02.2019 00:00:00
31.03.2019 00:00:00
30.04.2019 00:00:00
31.05.2019 00:00:00
30.06.2019 00:00:00
31.07.2019 00:00:00
31.08.2019 00:00:00
30.09.2019 00:00:00
31.10.2019 00:00:00
30.11.2019 00:00:00
31.12.2019 00:00:00
31.01.2020 00:00:00
18.02.2020 00:00:00

14 rows selected.

SQL>
0 голосов
/ 25 февраля 2020

Когда я впервые увидел это, я сразу подумал, что рекурсивный CTE будет идеальным. Проблема, с которой у меня возникало несоответствие типов в рекурсии, которую я не мог решить. Оказалось, что Oracle 11g содержит ошибку в рекурсивном CTE с рекурсивной датой. Это, наконец, заставило меня обновить в конце концов. Так что спасибо за вопрос. В любом случае для будущих зрителей рекурсивный CTE работает.

alter session set nls_date_format = 'yyyy-mm-dd';
with date_list (dte) as
   ( select last_day(date '2019-01-01') from dual   
     union all 
     select least(add_months(dte,1), trunc(sysdate))  
       from date_list
      where dte<trunc(sysdate)
   )  
select dte from date_list;  
...