По сути, проблема, с которой вы столкнулись, заключается в том, что ваш дизайн не нормализован и, как следствие, запросы на извлечение информации более сложны.В частности, первая таблица должна быть структурирована следующим образом:
Create Table MonthlyIndexes As
(
index_id int not null
, date datetime not null
, value ...
, Primary Key ( index_id, date )
, Constraint CK_MonthlyIndexes_Date Check ( DatePart(d, date) = 1 )
)
index_id | date | value
-------- -------- -------
1 | 20090301 | ...
1 | 20090401 | ...
...
Теперь запрос на получение необходимой информации становится проще:
Select S.saleprice * ( MStart.value / MEnd.value )
From Sales As S
Join MonthlyIndexes As MStart
On MStart.date = DateAdd(d, -DatePart(d, S.saledate) + 1)
Join MonthlyIndexes As MEnd
On MEnd.date = DateAdd(d, -DatePart(d, CURRENT_TIMESTAMP) + 1)
Запрет реструктуризации вашей схемы,вы можете смоделировать правильный дизайн следующим образом (предположим, что SQL Server 2005 +):
With Indexes As
(
Select index_id, Cast('20090301' As datetime) as date, Mar2009
From MonthlyIndexes
Union All
Select index_id, Cast('20090401' As datetime) as date, Apr2009
From MonthlyIndexes
....
Union All
Select index_id, Cast('20100201' As datetime) as date, Feb2010
From MonthlyIndexes
)
Select S.saleprice * ( MStart.value / MEnd.value )
From Sales As S
Join MonthlyIndexes As MStart
On MStart.date = DateAdd(d, -DatePart(d, S.saledate) + 1)
Join MonthlyIndexes As MEnd
On MEnd.date = DateAdd(d, -DatePart(d, CURRENT_TIMESTAMP) + 1)
Если таблица месячных индексов велика, вы можете выполнить периодические обновления нормализованной таблицы и использовать ее для своего запроса.1011 *
Другое решение состоит в том, чтобы периодически обновлять промежуточную таблицу с правильно структурированными данными, используя запрос, похожий на запрос Union All в моем CTE.Если данные добавляются один раз в месяц, вы можете даже добавить расписание, хранимое процедурой, которое проверяет, существует ли столбец для данного месяца, и добавляет данные этого месяца.Это будет включать в себя динамический SQL, который я обычно рекомендую использовать, однако для решения по техническому обслуживанию это может решить проблему (пока вы не убедите руководство исправить схему).