Гость
Целевая тема:
Создать новую тему:
Автор:
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Задача: определить ближайший к заданной дате год / 9 сообщений из 9, страница 1 из 1
22.11.2016, 22:15
    #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
22.11.2016, 22:49
    #39352291
SY
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
22.11.2016, 23:46
    #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
23.11.2016, 04:55
    #39352347
SY
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
23.11.2016, 13:43
    #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
23.11.2016, 14:25
    #39352731
dbms_photoshop
Участник
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Задача: определить ближайший к заданной дате год
SYНу насчет "и нужно" это бабушка надвое сказала. A вот пришпиндоливать GROUP BY уж точно не надоНасчет того, что group by не надо и что надо допилить для граничных условия согласен.

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

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

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

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


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