Вы заметили, что годы, которые дают вам проблемы, - это високосные годы? Проблема заключается в том, что число дней, следующего за 1 марта любого не-високосного года, будет меньше, чем число, указанное в тот же день в високосный год.
Один из способов рассчитать один и тот же день в течение многих лет - это хеш каждый день года в значение, которое в тот же день каждого года, прыжок и не-прыжок, будет иметь такое же значение и хэш 29 февраля будет между 28 февраля и 1 марта и не столкнется с каким-либо другим хэшем. Самый простой способ сделать это - умножить месяц на значение> 31 (количество дней в наибольшем месяце) и добавить день месяца. Любое значение> = 31 будет делать - даже круглое число, как 100. Это не красиво и не sargable:
Select Customer_Id, cust_birth_dt
From Customers
Where (Extract(Month From cust_birth_dt * 100 + Extract(Day From cust_birth_dt)
>= Extract(Month From SysDate) * 100 + Extract(Day From Sysdate))
and (Extract(Month From cust_birth_dt * 100 + Extract(Day From cust_birth_dt)
< Extract(Month From SysDate + 7) * 100 + Extract(Day From SysDate + 7));
Использование 100 позволяет быстро вычислить хэш только с первого взгляда на дата: 2/15/yyyy = 215, 10/25/yyy = 1025.
Теперь, чтобы сделать его красивее. Моделирование на помощь. Поскольку этот поиск по дням рождения, кажется, является тем, что выполняется один раз в неделю, создайте новую таблицу, а не добавьте новые столбцы в существующую таблицу.
create table Birthday_info(
Cust_ID int not null,
B_Date date not null,
B_Hash int not null,
constraint PK_Birthday_info primary key(Cust_ID),
constraint FK_Birthday_Customer foreign key(Cust_ID)
references Customers(customers_id)
);
Простой запрос может заполнить его на начальном этапе:
insert into Birthday_info
select customers_id, cust_birth_dt,
Extract(Month From cust_birth_dt) * 100 + Extract(Day From cust_birth_dt)
from Customers;
Чтобы обеспечить хорошую производительность:
create index IX_Birthday_Hash_ID on Birthday_info(B_Hash);
An "после вставки, обновления, удаления" триггер таблицы Customers может держать новая таблица обновлена.
Тогда ваш запрос будет:
Select Cust_Id, Birth_Dt
From Birthday_Info
Where B_Hash >= Extract(Month From Sysdate) * 100 + Extract(Day From SysDate)
And B_Hash < Extract(Month From Sysdate + 7) * 100 + Extract(Day From SysDate + 7);
Теперь sargable, но до сих пор не очень красиво. Тем не менее, вы можете создать функцию хеширования:
Select Cust_Id, Birth_Dt
From Birthday_Info
Where B_Hash >= Hash_pkg.Date_Hash(SysDate)
And B_Hash < Hash_pkg.Date_Hash(SysDate + 7);
Гораздо лучше.
Вы знаете, что это не работает в високосные годы?Кажется, он добавляет 7 дней к текущему дню, который, я считаю, должен правильно обрабатывать високосные годы. –
пример: когда я выбираю клиентов только с сегодняшнего дня, то есть 85 дней в году, я получаю за годы (2012,2008,2004 и т. Д.) Клиентов, у которых были дни рождения вчера. Он работает, но не дает мне результат мне нужен – Alexandru
Почему вы конвертируете даты в символы перед добавлением 7 семи дней? Каков тип этих полей? – pablomatico