Начальные данные записи в периодических регистрах сведений, значения о количестве жильцов и тарифы на разные даты, нужно одним запросом определить, сколько дней действует каждое значение количества и тариф, и выполнить начисление.
То есть, если данные о жильцах:
01.11.2011 = 1
05.11.2011 = 3
30.11.2011 = 2
А данных о тарифе:
01.11.2011 = 9,00
15.11.2011 = 11,50
То начисление за ноябрь должно быть:
С 01.11.2011 по 04.11.2011 = 1 * 9,00 (4 дня)
С 05.11.2011 по 14.11.2011 = 3 * 9,00 (10 дней)
С 15.11.2011 по 29.11.2011 = 3 * 11,50 (15 дней)
С 30.11.2011 по 30.11.2011 = 2 * 11,50 (1 день)
Для простоты примем, что тариф указан за день, в противном случае понадобится ещё коэффициент 4/30, 10/30, 15/30 и 1/30.
Решим в один запрос:
// Объединением, выберем дату начала, даты изменения жильцов, даты изменения ставок
// и чтоб не парится – дату конца периода
ВЫБРАТЬ
&НачПериода КАК Точки
ПОМЕСТИТЬ ВТ_Точки
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Жильцы.Период
ИЗ
РегистрСведений.Жильцы КАК Жильцы
ГДЕ
Жильцы.Период > &НачПериода
И Жильцы.Период < &КонПериода
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
Тарифы.Период
ИЗ
РегистрСведений.Тарифы КАК Тарифы
ГДЕ
Тарифы.Период > &НачПериода
И Тарифы.Период < &КонПериода
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
&КонПериода
;
// Дальше строим интервалы и сразу присоединяем даты актуальных значений жильцов и тарифов
// они меньше или равны началу каждого периода – максимальные из подходящих
ВЫБРАТЬ
ВТ_Точки.Точки КАК ДатаНачала,
МИНИМУМ(ВТ_Точки1.Точки) КАК ДатаКонца,
МАКСИМУМ(Жильцы.Период) КАК КорректЖильцов,
МАКСИМУМ(Тарифы.Период) КАК КорректТарифа
ПОМЕСТИТЬ ВТ_ВсеДаты
ИЗ
ВТ_Точки КАК ВТ_Точки
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_Точки КАК ВТ_Точки1
ПО ВТ_Точки.Точки < ВТ_Точки1.Точки
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Жильцы КАК Жильцы
ПО ВТ_Точки.Точки >= Жильцы.Период
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Тарифы КАК Тарифы
ПО ВТ_Точки.Точки >= Тарифы.Период
СГРУППИРОВАТЬ ПО
ВТ_Точки.Точки
;
// К полученной таблице присоединяем данные по актуальным датам,
// считаем РАЗНОСТЬДАТ и всё перемножаем, готово.
ВЫБРАТЬ
ВТ_ВсеДаты.ДатаНачала,
ВТ_ВсеДаты.ДатаКонца,
РАЗНОСТЬДАТ(ВТ_ВсеДаты.ДатаНачала, ВТ_ВсеДаты.ДатаКонца, ДЕНЬ) КАК БазаДней,
Жильцы.Количество,
Тарифы.Тариф,
РАЗНОСТЬДАТ(ВТ_ВсеДаты.ДатаНачала, ВТ_ВсеДаты.ДатаКонца, ДЕНЬ) * Жильцы.Количество * Тарифы.Тариф КАК Результат
ИЗ
ВТ_ВсеДаты КАК ВТ_ВсеДаты
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Жильцы КАК Жильцы
ПО ВТ_ВсеДаты.КорректЖильцов = Жильцы.Период
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.Тарифы КАК Тарифы
ПО ВТ_ВсеДаты.КорректТарифа = Тарифы.Период
Не стОит наверное подробно рассказывать о том, что заменив Жильцов на Сумму кредита, а Тариф на Процент можно с точностью до дней рассчитывать плату за использование кредита (кредитной карты), или начислять проценты по вкладу.
А используемый метод определения интервалов может работать с точностью до секунды при необходимости.
Так же может использоваться не ограничено большее количество регистров.
В архиве ПримерЗапроса содержится маленькая база данные под 8.1 (можно открыть и в 8.2), Список запросов для консоли и консоль запросов на всякий случай. Параметры берите с 01.11.2011 по 01.12.2011.
Файлы обработки:
- Primer_raschetov_po_registram_svedeniy,_Mikro_JKH,_opisanie_zaprosa.ZIP Для скачивания нужна регистрация