Создание подзапроса с набором дат (воскресений) между двумя точками - PullRequest
0 голосов
/ 27 июня 2018

Мне нужно сформировать несколько подзапросов с наборами дат, включая только воскресенья между двумя заданными точками, например, между 01.04.2018 и 30.06.2018.

Первое, что приходит в голову, это что-то вроде этого:

SELECT '01.04.2018' STARTDATE FROM DUAL
UNION ALL
SELECT '08.04.2018' STARTDATE FROM DUAL
...

Но выглядит не очень элегантно. Есть ли более простой способ добиться того, что мне нужно?

Ответы [ 2 ]

0 голосов
/ 27 июня 2018

Вы можете использовать:

SQL Fiddle

Запрос 1 :

SELECT NEXT_DAY( DATE '2018-04-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         AS startdate
FROM   DUAL
CONNECT BY
       NEXT_DAY( DATE '2018-04-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= DATE '2018-06-30'

Результаты :

|            STARTDATE |
|----------------------|
| 2018-04-01T00:00:00Z |
| 2018-04-08T00:00:00Z |
| 2018-04-15T00:00:00Z |
| 2018-04-22T00:00:00Z |
| 2018-04-29T00:00:00Z |
| 2018-05-06T00:00:00Z |
| 2018-05-13T00:00:00Z |
| 2018-05-20T00:00:00Z |
| 2018-05-27T00:00:00Z |
| 2018-06-03T00:00:00Z |
| 2018-06-10T00:00:00Z |
| 2018-06-17T00:00:00Z |
| 2018-06-24T00:00:00Z |

Всегда ли эта конструкция возвращает хотя бы одну строку? Если я добавлю дополнительное условие, что NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7 должно быть меньше SYSDATE, оно все равно возвращает первую строку, которая больше SYSDATE.

Да, иерархический запрос всегда будет возвращать одну строку, если фильтрация только что выполнена в предложении CONNECT BY (так как он будет проверять его только тогда, когда он пытается соединить одну строку со своим родителем и ему нужно сгенерировать хотя бы одну родитель, первым делающий это):

SELECT NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         AS startdate
FROM   DUAL
CONNECT BY
       NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= LEAST(
              SYSDATE, -- DATE '2018-06-29'
              DATE '2018-07-30'
            )

Результаты

|            STARTDATE |
|----------------------|
| 2018-07-01T00:00:00Z | -- Greater than SYSDATE

Но если вы добавите предложение WHERE (вместо фильтрации в предложении CONNECT BY), то он может вернуть ноль строк:

SELECT NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         AS startdate
FROM   DUAL
WHERE  NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= SYSDATE
CONNECT BY
       NEXT_DAY( DATE '2018-07-01' - 1, 'SUNDAY' ) + ( LEVEL - 1 ) * 7
         <= DATE '2018-07-30'

Результаты

No data found.
0 голосов
/ 27 июня 2018

Метод грубой силы заключается в том, чтобы просто сгенерировать весь диапазон дат, а затем отфильтровать его, чтобы оставить только воскресенья:

WITH cte AS (
    SELECT TRUNC (date '2018-06-30' - ROWNUM) dt
    FROM DUAL CONNECT BY ROWNUM < 100
)

SELECT * FROM cte WHERE TO_CHAR(dt, 'DAY') = 'SUN'
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...