В практике автоматизации сельскохозяйственных предприятий (АПК) часто возникает задача мониторинга продуктивности. Одной из наиболее сложных технических задач является выявление тренда на снижение показателей. В этой статье мы подробно разберем, как реализовать отчет, который будет выводить список животных, у которых наблюдается стабильное падение надоя в течение заданного количества дней. Мы проанализируем различные подходы: от классического соединения таблиц до использования математического анализа и современных оконных функций.
Предположим, у нас имеется оборотный регистр накопления Надои и справочник Животные. Основная сложность заключается в том, что условие "надой падает" — это не просто сравнение с нулем (как ошибочно предполагалось в начале обсуждения), а сравнение значения текущего дня со значением предыдущего. Более того, нам нужно подтвердить это падение на определенном временном интервале.
Рассмотрим пошагово, какими способами можно решить эту задачу в рамках языка запросов 1С.
Если мы работаем на платформе, не поддерживающей оконные функции, или нам нужно простое сравнение за два-три дня, мы можем использовать последовательное соединение таблиц оборотов. Разберем этот алгоритм.
Сначала подготовим данные за интересующий нас период, сгруппировав их по дням. Поместим результат во временную таблицу ВтОбороты. Далее мы будем соединять эту таблицу саму с собой со смещением по дате.
ВЫБРАТЬ
Надои.Животное КАК Животное,
НАЧАЛОПЕРИОДА(Надои.Период, ДЕНЬ) КАК Период,
СУММА(Надои.Количество) КАК Количество
ПОМЕСТИТЬ ВтОбороты
ИЗ
РегистрНакопления.Надои.Обороты(&НачалоПериода, &КонецПериода, День, ) КАК Надои
ГРУППИРОВАТЬ ПО
Надои.Животное,
НАЧАЛОПЕРИОДА(Надои.Период, ДЕНЬ)
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
Т1.Животное,
Т1.Период КАК Дата1,
Т1.Количество КАК Количество1,
Т2.Период КАК Дата2,
Т2.Количество КАК Количество2
ИЗ
ВтОбороты КАК Т1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВтОбороты КАК Т2
ПО Т1.Животное = Т2.Животное
И (ДОБАВИТЬКДАТЕ(Т1.Период, ДЕНЬ, 1) = Т2.Период)
ГДЕ
Т2.Количество < Т1.Количество
Проанализируем этот запрос: мы сопоставляем данные животного за "сегодня" и "вчера". Если Количество во второй таблице меньше, чем в первой, значит, за эти два дня зафиксировано падение. Чтобы проверить падение в течение, например, трех дней, нам потребуется добавить еще одно соединение с таблицей Т3.
Для более точного выявления тренда на длинных промежутках времени можно применить метод наименьших квадратов прямо в запросе 1С. Этот метод позволяет вычислить коэффициент наклона прямой (тренд). Если коэффициент отрицательный — общая динамика идет на спад.
Выясним причину эффективности этого метода: он сглаживает случайные колебания и дает общую картину за период. Рассмотрим пример реализации расчета коэффициента наклона b в уравнении y = ax + b.
ВЫБРАТЬ
Надои.Животное КАК Животное,
РАЗНОСТЬДАТ(&НачалоПериода, Надои.Период, СЕКУНДА) КАК X,
Надои.Количество КАК Y,
1 КАК N
ПОМЕСТИТЬ ВтДанные
ИЗ
РегистрНакопления.Надои КАК Надои
ГДЕ
Надои.Период МЕЖДУ &НачалоПериода И &КонецПериода
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВтДанные.Животное
ИЗ
ВтДанные КАК ВтДанные
ГРУППИРОВАТЬ ПО
ВтДанные.Животное
ИМЕЮЩИЕ
(СУММА(ВтДанные.N) * СУММА(ВтДанные.X * ВтДанные.Y) - СУММА(ВтДанные.X) * СУММА(ВтДанные.Y)) /
(СУММА(ВтДанные.N) * СУММА(ВтДанные.X * ВтДанные.X) - СУММА(ВтДанные.X) * СУММА(ВтДанные.X)) < 0
В данном запросе мы используем формулу для коэффициента регрессии. Если результат выражения в секции ИМЕЮЩИЕ меньше нуля, это математически доказывает наличие нисходящего тренда за весь указанный период. Важно: поле X (время) лучше приводить к числу секунд от начала периода, чтобы избежать работы с огромными числами.
Если ваша конфигурация работает на современной версии платформы 1С, задачу можно решить значительно элегантнее с помощью функции LAG. Эта функция позволяет получить значение из предыдущей строки результата запроса без использования сложных соединений.
Посмотрим, как это упрощает логику: мы можем вычислить разницу между текущим и прошлым значением в один проход.
ВЫБРАТЬ
Надои.Животное КАК Животное,
Надои.Период КАК Период,
Надои.Количество КАК ТекущийНадой,
LAG(Надои.Количество) НАД (ПОРЯДОК ПО Надои.Период ПАРТИЦИОНИРОВАТЬ ПО Надои.Животное) КАК ПредыдущийНадой
ПОМЕСТИТЬ ВтСравнение
ИЗ
РегистрНакопления.Надои.Обороты(&НачалоПериода, &КонецПериода, День, ) КАК Надои
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ
ВтСравнение.Животное,
ВЫБОР КОГДА ВтСравнение.ТекущийНадой < ВтСравнение.ПредыдущийНадой ТОГДА 1 ИНАЧЕ 0 КОНЕЦ КАК ФактПадения
ИЗ
ВтСравнение КАК ВтСравнение
После получения такой таблицы достаточно сгруппировать данные и подсчитать количество подряд идущих фактов падения. Это наиболее производительный метод для больших объемов данных.
При реализации подобных отчетов необходимо учитывать специфику работы с регистрами накопления:
&НачалоПериода и &КонецПериода в виртуальных таблицах.ИНДЕКСИРОВАТЬ ПО для полей Животное и Период. Это критически важно для производительности.АВТОНОМЕРЗАПИСИ() или оконную функцию ROW_NUMBER().Таким образом, мы рассмотрели три различных подхода к анализу динамики. Для простых задач подойдет соединение таблиц, для глубокого анализа трендов — математическая аппроксимация, а для современных систем — оконные функции. Выбор метода зависит от ваших требований к точности и версии используемой платформы 1С.