powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача: определить ближайший к заданной дате год
9 сообщений из 9, страница 1 из 1
Задача: определить ближайший к заданной дате год
    #39352281
Andrey19967
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Привет. Пожалуйста, нужна помощь, есть задача: определить ближайший к заданной дате год, когда 31 декабря придется на субботу .
Решение через рекурсию, то есть до того момента пока день недели в том (TEMP) году не будет равен 6.
Но загвоздка в том, что код не получается универсальным из-за того, что в WHERE для TEMP'а прописывается явно (к примеру < 2026). Подскажите как можно этого избежать?
(первая строка в with для примера)
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
WITH T(TEMP,NUMB) AS
(SELECT TO_NUMBER(TO_CHAR(TO_DATE('12.02.2018'),'YYYY')),TO_CHAR(TO_DATE('31.12.2018','DD.MM.YYYY'),'D')
FROM DUAL
UNION ALL
SELECT TEMP + 1, TO_CHAR(TO_DATE('31.12'||(TEMP+1),'DD.MM.YYYY'),'D') AS DATR
FROM T
WHERE TEMP < 2026 OR TO_CHAR(TO_DATE('31.12'||(TEMP+1),'DD.MM.YYYY'),'D') = 6)


SELECT * FROM T
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39352291
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey19967Решение через рекурсию, то есть до того момента пока день недели в том (TEMP) году не будет равен 6.


Ты будeшь удивлeн, но далеко во всех странaх недeля начинается с тяжелогo дня понедельника . Так что открой для себя формат IW:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
WITH T(
       DT
      ) AS (
             SELECT  TRUNC(DATE '2018-02-12','YY') + INTERVAL '1' YEAR - 1
               FROM  DUAL
            UNION ALL
             SELECT  DT + INTERVAL '1' YEAR
               FROM  T
               WHERE DT - TRUNC(DT,'IW') != 5
           )
SELECT  DT
  FROM  T
  WHERE DT - TRUNC(DT,'IW') = 5
/

DT
---------
31-DEC-22

SQL> 



SY.
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39352315
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey19967Подскажите как можно этого избежать?В подобных задачах можно (и нужно) самого recursive subquery factoring избежать

Код: plsql
1.
2.
3.
select max(add_months(dt, 12 * level)) dt
  from (select trunc(date '2018-02-12', 'YY') + interval '1' year - 1 dt from dual)
connect by add_months(dt, 12 * (level - 1)) - trunc(add_months(dt, 12 * (level - 1)), 'iw') <> 5
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39352347
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
dbms_photoshopВ подобных задачах можно (и нужно) самого recursive subquery factoring избежать


Ну насчет "и нужно" это бабушка надвое сказала. A вот пришпиндоливать GROUP BY уж точно не надо:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select add_months(dt, 12 * level) dt
  from (select trunc(date '2018-02-12', 'YY') + interval '1' year - 1 dt from dual)
where connect_by_isleaf = 1
connect by add_months(dt, 12 * (level - 1)) - trunc(add_months(dt, 12 * (level - 1)), 'iw') <> 5
/

DT
---------
31-DEC-22

SQL> 



Но это мелoчи, главное твое решение нерабочее:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
SQL> WITH T(
  2         DT
  3        ) AS (
  4               SELECT  TRUNC(DATE '2022-02-12','YY') + INTERVAL '1' YEAR - 1
  5                 FROM  DUAL
  6              UNION ALL
  7               SELECT  DT + INTERVAL '1' YEAR
  8                 FROM  T
  9                 WHERE DT - TRUNC(DT,'IW') != 5
 10             )
 11  SELECT  DT
 12    FROM  T
 13    WHERE DT - TRUNC(DT,'IW') = 5
 14  /

DT
---------
31-DEC-22

SQL> select max(add_months(dt, 12 * level)) dt
  2    from (select trunc(date '2022-02-12', 'YY') + interval '1' year - 1 dt from dual)
  3  connect by add_months(dt, 12 * (level - 1)) - trunc(add_months(dt, 12 * (level - 1)), 'iw') <> 5
  4  /

DT
---------
31-DEC-33

SQL> 



Так-что либо:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select add_months(dt, 12 * (level - 1)) dt
  from (select trunc(date '2022-02-12', 'YY') + interval '1' year - 1 dt from dual)
where connect_by_isleaf = 1
connect by add_months(dt, 12 * (level - 2)) - trunc(add_months(dt, 12 * (level - 2)), 'iw') <> 5
/

DT
---------
31-DEC-22

SQL> 



либо:

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
select add_months(dt, 12 * level) dt
  from (select trunc(date '2022-02-12', 'YY') - 1 dt from dual)
where connect_by_isleaf = 1
connect by add_months(dt, 12 * (level - 1)) - trunc(add_months(dt, 12 * (level - 1)), 'iw') <> 5
/

DT
---------
31-DEC-22

SQL> 



SY.
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39352679
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey19967,

Для рекурсивного варианта запроса формулировать стоп-условие я бы стал так:

вторую часть Union выдавать в выходной набор тех строк, у которых
в предшествующем наборе не было суббот или текущая строка содержит субботу.
Т.е.
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
23.
24.
25.
26.
27.
28.
29.
30.
31.
WITH T(r_date, n_year, NUMB, nocc) AS
(
Select  r_date
      , EXTRACT(YEAR FROM  r_date) as n_year 
      , TO_CHAR(r_date,'D') as numb
      , case WHEN to_char(r_date,'D') = to_char(Date '2000-01-01','D') 
          THEN 1
        ELSE 0
        END as nocc        
From (
      Select  Add_months(Trunc(to_date('2018','YYYY'),'YYYY'),11)+30 as r_date              
      From dual 
      )
Union All 
  Select Add_months(T.r_date,12) as r_date
        , T.n_year + 1 as n_year
        , to_char(Add_months(T.r_date,12),'D') as numb
        , case WHEN to_char(to_char(Add_months(T.r_date,12),'D')) = to_char(Date '2000-01-01','D') -- это суббота по госту РФ
          THEN 1 ELSE 0
          END as nocc        
  From T 
  Where 
  -- давай до первой возникшей субботы
    T.nocc = 0 
    OR  case WHEN to_char(Add_months(T.r_date,12),'D') = to_char(Date '2000-01-01','D') -- это суббота по госту РФ
          THEN 1
        ELSE 0
        END = 1
)
Select * From T 
Where nocc = 1 -- давай все получившиеся в наборе субботы
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39352731
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SYНу насчет "и нужно" это бабушка надвое сказала. A вот пришпиндоливать GROUP BY уж точно не надоНасчет того, что group by не надо и что надо допилить для граничных условия согласен.

А про "нужно" - rec with всегда (когда задача может быть решена connect by без перебора)
медленнее connect by, глючнее и больше букв.
Можно еще вспомнить про деградации типа current reads .

Конечно, если надо сгенерировать 10, 100, 10000 строк то пофиг.
Только не надо приучать к плохому.
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39353163
booby
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
SY,

при первом чтении проскользил мимо твоего первого в теме поста.
сейчас перечитал - ++!
Дважды красивый заход.
Разглядывать - маленькое, но вполне отчетливое удовольствие.
Как коньяк средних лет - с выраженным, но не навязчивым ароматом.
Спасибо.
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39354115
Andrey19967
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
booby, большое спасибо, вот примерно такое что-то и хотелось реализовать, но немного не хватило
...
Рейтинг: 0 / 0
Задача: определить ближайший к заданной дате год
    #39354134
Фотография dbms_photoshop
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Andrey19967,

То, что здесь "рекурсия" не нужна до тебя так и не дошло?
...
Рейтинг: 0 / 0
9 сообщений из 9, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача: определить ближайший к заданной дате год
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]