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