powered by simpleCommunicator - 2.0.50     © 2025 Programmizd 02
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Интервал по дням рождения PL/SQL
12 сообщений из 12, страница 1 из 1
Интервал по дням рождения PL/SQL
    #40078749
Всем привет. Не получается решить часть задачи, с датами вообще не дружу и не могу найти нормального варианта, весь интернет раскопал, но ничего не нашел. может вы поможете. Буду очень благодарен!

Задача состоит в том что нужно определить попадает ли SYSDATE в интервал между днем рождения - 2 дня и днем рождения + 3 дня.

Вот что у меня получилось:

Код: plsql
1.
2.
SYSDATE BETWEEN TO_DATE(d_date_br + NUMTOYMINTERVAL((extract(year from sysdate)-(extract(year from d_date_br))), 'year') - 2) 
  AND TO_DATE(d_date_br + NUMTOYMINTERVAL((extract(year from sysdate)-(extract(year from d_date_br))), 'year') + 3



Но я не учел того что если день рождения будет, например, 31.12.1990, а SYSDATE будет 01.01.2021, то запрос не будет работать праввильно. Я думаю что все же не правильный подход выбрал для этой задачи. Если хотябы подскажете не много, буду благодарен! Заранее спасибо!
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40078767
Правильный Вася
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
sysdate between birth_date-2 and birth_date+3
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40078771
Правильный Вася,
К сожалению 10.05.2021 не войдет в интервал между 08.05.1990 и 14.05.1990
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40078781
va_kochnev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вася Кропоткин,
Код: plsql
1.
2.
3.
with a as (select to_date('10.06.1940','DD.MM.YYYY') d_date_br from dual)
select d_date_br, trunc(sysdate)- add_months(d_date_br, months_between(trunc(sysdate,'YYYY') ,trunc(d_date_br,'YYYY')))
from a;
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40078909
va_kochnev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
va_kochnev
Вася Кропоткин,
Код: plsql
1.
2.
3.
with a as (select to_date('10.06.1940','DD.MM.YYYY') d_date_br from dual)
select d_date_br, trunc(sysdate)- add_months(d_date_br, months_between(trunc(sysdate,'YYYY') ,trunc(d_date_br,'YYYY')))
from a;


Вышеприведенный запрос показывает разницу в дня для ДР текущего календарного года.
Если нужен ближай ДР (прошедший или будущий), то надо больше накрутить, найдя наименьшую разницу в днях для ДР текущего, прошлого и будущего годов:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
with a as (select to_date('01.01.2020','DD.MM.YYYY') d_date_br, to_date('30.12.2020','DD.MM.YYYY') sysdate_  from dual)
, b as (select a.*
, add_months(d_date_br, months_between(trunc(sysdate_,'YYYY') ,trunc(d_date_br,'YYYY'))) cur_date_br
, add_months(d_date_br, months_between(trunc(sysdate_,'YYYY') ,trunc(d_date_br,'YYYY'))-12) prev_date_br
, add_months(d_date_br, months_between(trunc(sysdate_,'YYYY') ,trunc(d_date_br,'YYYY'))+12) next_date_br
from a)
, c as (select b.*, least(
abs(trunc(sysdate_)-cur_date_br),
abs(trunc(sysdate_)-next_date_br),
abs(trunc(sysdate_)-prev_date_br) 
) least_days
 from b)
select c.*,
case when abs(trunc(sysdate_)-cur_date_br)=least_days then trunc(sysdate_)-cur_date_br
     when abs(trunc(sysdate_)-prev_date_br)=least_days then trunc(sysdate_)-prev_date_br
     when abs(trunc(sysdate_)-next_date_br)=least_days then trunc(sysdate_)-next_date_br
end between_days
 from c;


В реальном коде надо будет SYSDATE_ заменить на SYSDATE. Ну и, если речь именно про PL/SQL, то завести вспомогательные переменные, а не накручивать подзапросы, как в примере.
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40078914
Фотография mRdUKE
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вася Кропоткин
нужно определить попадает ли SYSDATE в интервал между днем рождения - 2 дня и днем рождения + 3 дня.
Код: sql
1.
to_char(sysdate,'ddmm') in (select to_char(d_date_br-3+level,'ddmm') from dual connect by level<7)
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40078945
va_kochnev
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
mRdUKE
Вася Кропоткин
нужно определить попадает ли SYSDATE в интервал между днем рождения - 2 дня и днем рождения + 3 дня.
Код: sql
1.
to_char(sysdate,'ddmm') in (select to_char(d_date_br-3+level,'ddmm') from dual connect by level<7)


Если ДР приходится на конец февраля/начало марта, то из-за "разновисокосности" года рождения и текущего года будет засада.
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40079042
Фотография Stax
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вася Кропоткин,

если я правильно понял
перефразирую
день рождения был недавно(-2/+3 дня)

даты без времени (trunc(sysdate))

Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
with t as(
select to_date('08.05.1990','dd.mm.yyyy') br from dual union all
select to_date('05.01.1962','dd.mm.yyyy') br from dual union all
select trunc(sysdate)-3 br from dual union all
select trunc(sysdate)-2 br from dual union all
select trunc(sysdate)   br from dual union all
select trunc(sysdate)+3 br from dual union all
select trunc(sysdate)+4 br from dual
)
,s as(
select to_date('10.05.2021','dd.mm.yyyy') sysdat from dual
union all
select trunc(sysdate)   br from dual
)
select s.*,t.*
,case when floor(months_between(sysdat-2-1/24/60/60,br)/12)<>floor(months_between(sysdat+3,br)/12) 
  then 'Y' 
  else 'N' end recently
from s,t
order by 1,2



SYSDATBRRECENTLY10.05.202105.01.1962N10.05.202108.05.1990Y10.05.202117.06.2021N10.05.202118.06.2021N10.05.202120.06.2021N10.05.202123.06.2021N10.05.202124.06.2021N20.06.202105.01.1962N20.06.202108.05.1990N20.06.202117.06.2021N20.06.202118.06.2021Y20.06.202120.06.2021Y20.06.202123.06.2021Y20.06.202124.06.2021N

ps
если надо
допилить/проверить переход ер, смена календаря, немовляты, секунды и тд

.....
stax
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40079044
Фотография SY
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
va_kochnev
mRdUKE
пропущено...
Код: sql
1.
to_char(sysdate,'ddmm') in (select to_char(d_date_br-3+level,'ddmm') from dual connect by level<7)


Если ДР приходится на конец февраля/начало марта, то из-за "разновисокосности" года рождения и текущего года будет засада.


Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
20.
21.
22.
with t as (
           select  b_day,
                   case
                     when     to_char(b_day,'mmdd') = '0229'                                     -- если день рождения 29 февраля
                          and to_char(add_months(trunc(sysdate,'yyyy'),3) - 1,'mmdd') != '0229'  -- а текущий год не високосный то
                       then to_date(to_char(sysdate,'YYYY"0228"'),'YYYYMMDD')                    -- считаем текущий день рождения 28 февраля
                       else to_date(to_char(sysdate,'YYYY') || to_char(b_day,'MMDD'),'YYYYMMDD') -- иначе b_day этого года
                   end this_year_b_day,
                   case
                     when trunc(sysdate,'YYYY') = trunc(b_day,'YYYY') then null                            -- родился в этом году
                     when     to_char(b_day,'mmdd') = '0229'                                               -- если день рождения 29 февраля
                          and to_char(add_months(trunc(sysdate,'yyyy'),-10) - 1,'mmdd') != '0229'          -- а прошлый год не високосный то
                       then to_date((to_char(sysdate,'yyyy') - 1) || '/0228','YYYY/MMDD')                  -- считаем прошлогодний день рождения 28 февраля
                       else to_date((to_char(sysdate,'YYYY') - 1) || to_char(b_day,'"/"MMDD'),'YYYY/MMDD') -- иначе b_day прошлого года
                   end last_year_b_day
             from  tbl
          )
select  *
  from  t
  where trunc(sysdate) between this_year_b_day - 2 and this_year_b_day + 3
     or trunc(sysdate) between last_year_b_day - 2 and last_year_b_day + 3
/



SY.
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40079061
Фотография Elic
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40079093
Всем спасибо за помощь! Но подошел вариант с формула вычисления дня рождения, ближайшего к искомой дате . Я видел его но почему-то не разобравшись посчитал что он не подходит. Скорее всего нужно было просто отвлечься от работы. Отдельное спасибо Elic.
...
Рейтинг: 0 / 0
Интервал по дням рождения PL/SQL
    #40079100
freecozoid
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Как вариант:
Код: plsql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
with days as  (
     select  to_date('31.12.1990', 'dd.mm.yyyy') birth_day, 
             to_date('01.01.1991', 'dd.mm.yyyy') sys_date   
       from  dual 
), 
days_offset as (
     select  birth_day - trunc(birth_day, 'yyyy') birth_day_offset ,
             sys_date  - trunc(sys_date,  'yyyy') sys_day_offset
     from    days
)
select birth_day_offset, sys_day_offset
from   days_offset

where  sys_day_offset       between birth_day_offset - 2 and birth_day_offset + 3 
or     sys_day_offset + 365 between birth_day_offset - 2 and birth_day_offset + 3 
...
Рейтинг: 0 / 0
12 сообщений из 12, страница 1 из 1
Форумы / Oracle [игнор отключен] [закрыт для гостей] / Интервал по дням рождения PL/SQL
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


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