powered by simpleCommunicator - 2.0.61     © 2026 Programmizd 02
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Форумы / Firebird, InterBase [игнор отключен] [закрыт для гостей] / Как узнать завтрашних именинников?
25 сообщений из 63, страница 1 из 3
Как узнать завтрашних именинников?
    #37731832
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Что-то я совсем запутался.

Есть таблица:
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
recreate table td(mem_date date);
insert into td(mem_date)values('30-Mar-2008');
insert into td(mem_date)values('30-Mar-2009');
insert into td(mem_date)values('30-Mar-2010');
insert into td(mem_date)values('30-Mar-2011');
insert into td(mem_date)values('31-Mar-2008');
insert into td(mem_date)values('31-Mar-2009');
insert into td(mem_date)values('31-Mar-2010');
insert into td(mem_date)values('31-Mar-2011');
insert into td(mem_date)values('01-Apr-2008');
insert into td(mem_date)values('01-Apr-2009');
insert into td(mem_date)values('01-Apr-2010');
insert into td(mem_date)values('01-Apr-2011');



Пробуем узнать, есть ли завтра причина для пьянки:
Код: sql
1.
2.
3.
4.
5.
select
  *
from td
where 
  extract(yearday from mem_date) = extract(yearday from dateadd(1 day to current_date))


Хм. Не то. А если
Код: sql
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.
select
  *
from td
where 
  (--до 28 февраля включительно все без проблем
  extract(yearday from current_date) < 60
  and extract(yearday from mem_date) = extract(yearday from dateadd(1 day to current_date))
  )
  or --если именинник в невысокосном году и текущий год невысокосный
  (mod(extract(year from current_date), 4) > 0
   and mod(extract(year from mem_date), 4) > 0
   and extract(yearday from mem_date) = extract(yearday from dateadd(1 day to current_date))
  )
  or --если именинник в высокосном году и текущий год высокосный
  (mod(extract(year from current_date), 4) = 0
   and mod(extract(year from mem_date), 4) = 0
   and extract(yearday from mem_date) = extract(yearday from dateadd(1 day to current_date))
  )
  or --если именинник в невысокосном году, а текущий год высокосный
  (mod(extract(year from current_date), 4) = 0
   and mod(extract(year from mem_date), 4) > 0
   and extract(yearday from current_date) > 60
   and extract(yearday from mem_date) = extract(yearday from dateadd(0 day to current_date))
   )
  or --если именинник в высокосном году, а некущий год невысокосный
  (mod(extract(year from current_date), 4) > 0
   and mod(extract(year from mem_date), 4) = 0
   and extract(yearday from current_date) > 60
   and extract(yearday from mem_date) = extract(yearday from dateadd(-1 day to current_date))
   )


Уже лучше, но я не уверен, что я все проверки сделал правильно и учел все нюансы с датами.

И вообще, может есть более простой/правильный путь?
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731849
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonline,

Код: sql
1.
where memdate-current_date = 1
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731855
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

На приведенных в первом посте данных для сегодняшнего дня видает NULL. Еще идеи?
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731865
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
а зачем весь геморой с yearday?
не проще проверять day и month?
композитный индекс в помощь.

p.s. придется особым образом обработать только родившихся 29.02, если есть строгое указание не промогать ни одного повода для пьянки.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731875
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonlinem7m,

На приведенных в первом посте данных для сегодняшнего дня видает NULL. Еще идеи?

ууу, я протупил, по поводу сути задачи
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731926
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonline,

ну что то вот такое

(Месяц(current_date+1) = месяц(mem_date) and День(current_date+1) = День(mem_date))
или
(месяц(mem_date) = 2 and День(mem_date) = 29 and Месяц(current_date+1) = 3 and День(current_date+1)=1
and not ( Месяц(current_date+1) = 2 и День(current_date+1)=29))

если родившихся 29 февраля будут "обмывать" 1-го марта
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731943
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arniа зачем весь геморой с yearday?
не проще проверять day и month?
композитный индекс в помощь.

p.s. придется особым образом обработать только родившихся 29.02, если есть строгое указание не промогать ни одного повода для пьянки.

Один день на четыре года можно и пропустить. Хотя, конечно, нежелательно - там у меня как раз племянник родился :)
Геморой с yearday потому, что на тот момент это было первое что пришло в голову.
Спасибо за идею, запрос с этажерки в первом посте сократился до
Код: sql
1.
2.
3.
4.
5.
6.
select
  *
from td
where 
  extract(month from mem_date) = extract(month from dateadd(1 day to current_date))
  and extract(day from mem_date) = extract(day from dateadd(1 day to current_date))


//Пошел прогонять его на всех возможных датах для поиска ошибки.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731957
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
m7m,

Да, спасибо - как раз на 29 февраля мой запрос и будет сыпаться.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37731969
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Вот такой запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select
  *
from td
where 
  (
  extract(month from mem_date) = extract(month from dateadd(1 day to :current_date))
  and extract(day from mem_date) = extract(day from dateadd(1 day to :current_date))
  )
  or
  (
  extract(month from mem_date) = 2 and extract(day from mem_date) = 29
  and extract(month from dateadd(1 day to :current_date)) = 3
  and extract(day from dateadd(1 day to :current_date)) = 1
  )


у меня правильно переварил все даты, которые я ему подсунул.
Всем спасибо :)
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37732007
Фотография arni
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonline,

если хотите ускориться, тогда вычисляйте однократно
extract(month from dateadd(1 day to current_date))
и
extract(day from dateadd(1 day to current_date))
и передавайте в качестве переменных.

а то мой склероз шепчет, они будут вычисляться для каждой строки вновь и вновь.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37732021
Фотография Di_LIne
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
arniа зачем весь геморой с yearday?
не проще проверять day и month?
композитный индекс в помощь.

p.s. придется особым образом обработать только родившихся 29.02, если есть строгое указание не промогать ни одного повода для пьянки.
Прощее - сделать поле "MMDD" с индексом и не морщить ни кому голову: ни себе, ни серверу... :)
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37732117
m7m
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonlineВот такой запрос
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
select
  *
from td
where 
  (
  extract(month from mem_date) = extract(month from dateadd(1 day to :current_date))
  and extract(day from mem_date) = extract(day from dateadd(1 day to :current_date))
  )
  or
  (
  extract(month from mem_date) = 2 and extract(day from mem_date) = 29
  and extract(month from dateadd(1 day to :current_date)) = 3
  and extract(day from dateadd(1 day to :current_date)) = 1
  )


у меня правильно переварил все даты, которые я ему подсунул.
Всем спасибо :)

и в высокосный год, родившиеся 29-го февраля будут праздновать день рождение два дня
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37744666
zeon11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonline,

Ещё раз извиняюсь, продублировал теперь здесь.

Выборка персонала, с днём рождения в ближайшие 20 дней

Код: sql
1.
2.
3.
4.
select p.family, p.dtr  
    from personnel p
     where extract(yearday from p.dtr)-extract(yearday from cast('NOW' as date)) between 0 and 20
        or extract(yearday from p.dtr)-extract(yearday from cast('NOW' as date)) <20-365



Родившихся 29 февраля сей запрос отработал нормально, специально проверил
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #37744714
Oliph_
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Ну ее, эту тему...

Модератор: Удалено.
У нас технический форум, религиозные аспекты мы не рассматриваем.
...
Рейтинг: 0 / 0
Период между сообщениями больше года.
Как узнать завтрашних именинников?
    #38379204
zeon11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zeon11miwaonline,

Ещё раз извиняюсь, продублировал теперь здесь.

Выборка персонала, с днём рождения в ближайшие 20 дней

Код: sql
1.
2.
3.
4.
select p.family, p.dtr  
    from personnel p
     where extract(yearday from p.dtr)-extract(yearday from cast('NOW' as date)) between 0 and 20
        or extract(yearday from p.dtr)-extract(yearday from cast('NOW' as date)) <20-365



Родившихся 29 февраля сей запрос отработал нормально, специально проверил

Для исполнения запроса в високосный год 365 заменить на 366, если лениво вспоминать, какой нонче год, то для определения количества дней в году выполнить запрос, предложенный в своё время KDV 3989390 :
Код: sql
1.
2.
select extract(yearday from cast('31.12.'||extract(year from current_date) as date))+1
from rdb$database
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38380175
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Хорошая задачка :)
У меня вот такое получилось для сегодняшних (для завтрашних CURRENT_TIMESTAMP сменить на DATEADD(1 DAY TO CURRENT_TIMESTAMP).
Код: sql
1.
2.
3.
4.
5.
6.
7.
8.
9.
10.
11.
12.
13.
14.
15.
16.
17.
18.
19.
SELECT Birthdate
  FROM (SELECT
          Birthdate,
          EXTRACT(MONTH FROM birthdate) as M_BD, EXTRACT(DAY FROM birthdate) as D_BD,
          EXTRACT(MONTH FROM CURRENT_TIMESTAMP) AS M_Now,
          EXTRACT(DAY FROM CURRENT_TIMESTAMP) AS D_Now,
          EXTRACT(YEARDAY FROM CAST('31.12.' || EXTRACT(YEAR FROM CURRENT_TIMESTAMP) AS DATE) + 1) AS Now_DayCnt
        FROM tabletest)
WHERE  -- Not 29/02 - simple case
       ( D_BD <> 29 AND M_BD <> 2 AND
         M_BD = M_Now AND D_BD = D_Now ) OR
       -- 29/02
       ( D_BD = 29 AND M_BD = 2 AND
         -- Leap year => Exact match
         (Now_DayCnt = 366 AND
          M_BD = M_Now AND D_BD = D_Now ) OR
         -- Not leap year => 29/02 = 01/03
         (Now_DayCnt = 365 AND
          M_Now = 3 AND D_Now = 1) )


Ценой джойна временных переменных условия запроса сокращены до удобочитаемого вида
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38383919
Konstantin.Ogorodov
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
В решении предложенном zeon11 содержится ошибка: нумерация дней для высокосных и не выскосных годов не будут совпадать на 1 день из-за 29 февраля.

По этой причине пришлось изобретать свой велосипед. Необходимо было найти именинников в указанном периоде (!!!), а не за 1 день. Ключевым приёмом в решении было вычисление "магического числа": номер месяца рождения * 100 + число рождения. Аналогичные преобразования были сделаны для интервала и таким образом в условии where для большинства случаев получаем условие "MagicNumber between IntervalStart and IntervalEnd". Отдельно нужно обрабатывать случай перехода интервала на следующий год, тогда: IntervalStart > IntervalEnd and (MagicNumber >= IntervalStart or MagicNumber < = IntervalEnd).

Дата дня рождения вычисляется путём добавления к дате рождения разницы в годах между последней и текущим годом. Однако если IntervalStart > IntervalEnd /* переход интервала на след. год */ and MagicNumber <= IntervalEnd, то нужно добавить ещё годик.

Готовый запрос не даю, дабы была возможность пошевелить мозгами самостоятельно... А может и потому, что запрос писался для MS SQL и переделывать под синтаксис FireBird нет желания.

P.S. MS SQL позволяет создать MagicNumber как вычисляемое поле с построением индекса по нему, что позволит сделать запрос эффективным на больших объёмах данных.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384270
Ivan_Pisarevsky
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Konstantin.OgorodovP.S. MS SQL позволяет создать MagicNumber как вычисляемое поле с построением индекса по нему, что позволит сделать запрос эффективным на больших объёмах данных.ФБ тоже. Более того, можно сделать индекс по выражению и не хранить калькулируемое поле вообще.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384366
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
Konstantin.Ogorodov,

корректно работает в случае, если год рождения был високосным?

P.S. Что за всеобщая эпидемия написания слова "високосный" через Ы?
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384500
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Fr0sT-BrutalP.S. Что за всеобщая эпидемия написания слова "високосный" через Ы?
А это привет с Украины ;) У нас это слово читается и пишется как «вЫсокосный» (украинская «и» по звучанию еквивалентна русской «ы»), соответственно так и «переводим» на братский язык (отталкиваясь от слова «высокий»). Так что это слово можно считать таким себе индикатором украинцев :)
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384563
Fr0sT-Brutal
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Гость
miwaonline,

ну так и пишите это слово "по-украински" :) Хотя, тогда получится "високосн и й"...
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384633
zeon11
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
"Как узнать завтрашних именинников?"

Кто может задать этот вопрос и кому ответ на него нужен?
Очевидно, что этот вопрос актуален для людей кадровой службы, опасающихся пропустить день рождения сотрудников, не отметив уважаемых людей в приказе по учреждению и т.п. 20 дней запаса - срок, за который можно подготовится к любому событию.
Будет-ли сотрудник в списке 19 дней или 21 не столь важно, главное, что он всё это время будет в списке и его точно поздравят вовремя.
Городить трёхэтажный запрос ради формальной правильности - это конечно дело вкуса, но тогда следует уж идти до конца и учитывать, что високосный год это год, номер которого кратен четырём, за исключением годов, кратных 100, но года кратные 400 по-прежнему будут високосными.
Иными словами, 2000 год високосный, 2100, 2200, 2300 - не високосные, 2400 - високосный.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384656
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Все это легко организовывается через "рабочий календарь", разложенный на дни и месяцы. Но там обычно еще есть и кварталы, выходные, рабочие, праздничные дни и т.п. Штука полезная.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384673
miwaonline
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
zeon11,

Поскольку инициатор вопроса - я, то мне этот запрос нужен чтобы софт автоматически рассылал поздравительные СМС постоянным клиентам в день рождения. Так что о 20 днях ожидания и формальной правильности речь (в моем случае) не идет. Так же как и о именинниках в 2100 году - меня этот вопрос тоже вряд ли будет волновать :)

Поэтому и рабочий календарь, предложенный wadman-ом мне также не подходит.
...
Рейтинг: 0 / 0
Как узнать завтрашних именинников?
    #38384677
Фотография wadman
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
miwaonlineПоэтому и рабочий календарь, предложенный wadman-ом мне также не подходит.
Причина и следствие не понятны. Что такое "рабочий календарь" тебе известно?

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


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