Пример расчетов по регистрам сведений, Микро ЖКХ, описание запроса


Как пример расчета начислений с изменяющейся базой и плавающим тарифом приводится задачка «Микро ЖКХ».

Начальные данные записи в периодических регистрах сведений, значения о количестве жильцов и  тарифы на разные даты, нужно одним запросом определить, сколько дней действует каждое значение количества и тариф, и выполнить начисление.

То есть, если данные о жильцах:

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.

Файлы обработки:

-