При работе с документами корректировки реализации в 1С (особенно в конфигурациях ERP, УТ 11 или КА) часто возникает задача: получить только последний, актуальный документ из цепочки исправлений. Поскольку одна реализация может корректироваться несколько раз, простым запросом к таблице Документ.КорректировкаРеализации мы получим все документы, включая те, которые уже утратили актуальность. В этой статье мы разберем несколько профессиональных способов решения этой задачи, проанализируем их плюсы и минусы, а также узнаем, как сделать запрос максимально производительным.
Этот способ считается классическим и наиболее гибким. Основная идея заключается в том, чтобы попытаться соединить таблицу корректировок с этой же таблицей еще раз, но по условию, что дата второго документа больше даты первого. Если для конкретной корректировки "будущего" документа не нашлось, значит, она и есть последняя.
Рассмотрим подробнее реализацию этого метода на примере запроса:
ВЫБРАТЬ
Корр1.Ссылка КАК АктуальнаяКорректировка,
Корр1.ИсходныйДокументРеализации КАК Реализация
ИЗ
Документ.КорректировкаРеализации КАК Корр1
ЛЕВОЕ СОЕДИНЕНИЕ Документ.КорректировкаРеализации КАК Корр2
ПО Корр1.ИсходныйДокументРеализации = Корр2.ИсходныйДокументРеализации
И Корр1.Дата < Корр2.Дата
И Корр2.Проведен = ИСТИНА
ГДЕ
Корр1.Проведен = ИСТИНА
И Корр2.Ссылка ЕСТЬ NULL
И Корр1.ИсходныйДокументРеализации В (&МассивРеализаций)
Разберем по шагам, что происходит в этом запросе:
Корр1).Корр2) по тому же самому исходному документу.Корр1.Дата < Корр2.Дата ищет документы, созданные позже текущего.Корр2.Ссылка ЕСТЬ NULL оставляет только те записи из Корр1, для которых "более позднего" документа не существует. Это и гарантирует нам получение финального звена в цепочке.Важное замечание: Если в системе возможны корректировки с абсолютно идентичной датой и временем (до секунды), этот запрос может вернуть дубли. Чтобы этого избежать, в условии соединения вместо Дата лучше использовать комбинацию даты и ссылки или обратиться к понятию "Момент времени".
В платформе 1С идентификатор Ссылка содержит в себе временную составляющую. В большинстве случаев (хотя это и не документировано как абсолютное правило) более поздний документ будет иметь "большую" ссылку при сравнении. Это позволяет использовать агрегатные функции в группировках.
Проанализируем пример использования группировки:
ВЫБРАТЬ
МАКСИМУМ(Корректировка.Ссылка) КАК Ссылка,
Корректировка.ИсходныйДокументРеализации КАК Реализация
ИЗ
Документ.КорректировкаРеализации КАК Корректировка
ГДЕ
Корректировка.Проведен = ИСТИНА
ГРУППИРОВАТЬ ПО
Корректировка.ИсходныйДокументРеализации
Этот метод работает быстрее, так как не требует тяжелых соединений. Однако он менее надежен в распределенных базах данных (РИБ) или при массовом переносе данных, где порядок генерации ссылок может не совпадать с хронологией создания документов. Используйте этот метод, если уверены в последовательности ввода данных в вашей системе.
В типовых решениях (ERP, УТ 11) каждая корректировка может ссылаться либо на исходную реализацию, либо на предыдущую корректировку. Второе часто происходит при исправлении ошибок. В поле ДокументРеализации записывается тот документ, который мы правим в данный момент.
Выясним причину, по которой это поле помогает найти финал цепочки: актуальная корректировка — это та, на которую еще никто не сослался в качестве "исправляемого" документа. Посмотрим на пример кода:
ВЫБРАТЬ
ВсеКорр.Ссылка
ИЗ
Документ.КорректировкаРеализации КАК ВсеКорр
ГДЕ
ВсеКорр.Проведен = ИСТИНА
И НЕ ВсеКорр.Ссылка В (
ВЫБРАТЬ
Док.ДокументРеализации
ИЗ
Документ.КорректировкаРеализации КАК Док
ГДЕ
Док.Проведен = ИСТИНА
)
Этот подход логически безупречен для конфигураций, использующих цепочки исправлений. Мы просто исключаем из выборки все ссылки, которые упоминаются в колонке ДокументРеализации у других корректировок.
Чтобы ваш запрос не "вешал" систему при большом количестве данных, рекомендуем придерживаться следующих правил:
Реализация.ИсходныйДокументРеализации, ДокументРеализации), проиндексированы. В типовых конфигурациях эти поля обычно являются индексируемыми по умолчанию.Статус = ЗНАЧЕНИЕ(Перечисление.СтатусыКорректировокРеализации.Выполнена).ВыручкаИСебестоимостьПродаж). Платформа 1С делает это гораздо эффективнее, чем ручной перебор документов в запросе.Рассмотрим, как правильно подготовить временную таблицу с индексами для повышения производительности:
// Помещаем исходные данные во временную таблицу
ВЫБРАТЬ
Корр.Ссылка КАК Ссылка,
Корр.Дата КАК Дата,
Корр.ИсходныйДокументРеализации КАК ИсходныйДокумент
ПОМЕСТИТЬ ВТ_ВсеКорректировки
ИЗ
Документ.КорректировкаРеализации КАК Корр
ГДЕ
Корр.Проведен = ИСТИНА
И Корр.Дата МЕЖДУ &НачалоПериода И &КонецПериода;
ИЗМЕНИТЬ ВТ_ВсеКорректировки
ДОБАВИТЬ ИНДЕКС ПО ИсходныйДокумент, Дата;
// Теперь выбираем актуальные записи
ВЫБРАТЬ
Т1.Ссылка
ИЗ
ВТ_ВсеКорректировки КАК Т1
ЛЕВОЕ СОЕДИНЕНИЕ ВТ_ВсеКорректировки КАК Т2
ПО Т1.ИсходныйДокумент = Т2.ИсходныйДокумент
И Т1.Дата < Т2.Дата
ГДЕ
Т2.Ссылка ЕСТЬ NULL;
Подводя итог, можно сказать, что выбор метода зависит от конкретной конфигурации и требований к точности. Для простых задач подходит Метод 2 (Группировка), для сложных систем с длинными цепочками исправлений лучше использовать Метод 1 (Левое соединение) или Метод 3 (Исключение по ссылкам).