В процессе разработки бизнес-логики часто возникает задача сверки данных внутри одного объекта. Например, при закрытии заказа поставщику необходимо убедиться, что фактически полученные товары в табличной части ОтметкиСклада полностью соответствуют плановым позициям из таблицы Товары. Проверка должна учитывать не только перечень номенклатуры, но и характеристики, а также количество.
Рассмотрим, как реализовать такую проверку наиболее эффективно, избежав типичных ошибок новичков, и почему стандартные соединения таблиц не всегда являются лучшим выбором.
На первый взгляд кажется, что задачу можно решить простым перебором строк или использованием ПОЛНОЕ СОЕДИНЕНИЕ в запросе. Однако при работе с табличными частями (ТЧ) мы сталкиваемся с рядом нюансов:
NULL, которые требуют дополнительной обработки функцией ЕСТЬNULL.Проанализируем наиболее изящный и надежный способ решения — метод «зеркального» суммирования через объединение таблиц.
Суть метода заключается в создании единого набора данных из двух таблиц. Для первой таблицы мы берем количество со знаком «плюс», а для второй — со знаком «минус». Если содержимое таблиц идентично, то после группировки по ключевым полям (Номенклатура, Характеристика) сумма количеств по каждой позиции должна обнулиться.
Разберем реализацию этого алгоритма на примере запроса:
ВЫБРАТЬ
Табличка.Номенклатура КАК Номенклатура,
Табличка.Характеристика КАК Характеристика,
СУММА(Табличка.Количество) КАК ПолеРазницы
ИЗ
(ВЫБРАТЬ
ТЧ_Отметки.Номенклатура КАК Номенклатура,
ТЧ_Отметки.Характеристика КАК Характеристика,
ТЧ_Отметки.КоличествоПолученоСкладом КАК Количество
ИЗ
Документ.ПредварительныйЗаказПоставщику.ОтметкиСклада КАК ТЧ_Отметки
ГДЕ
ТЧ_Отметки.Ссылка = &Ссылка
ОБЪЕДИНИТЬ ВСЕ
ВЫБРАТЬ
ТЧ_Товары.Номенклатура,
ТЧ_Товары.Характеристика,
-ТЧ_Товары.Количество
ИЗ
Документ.ПредварительныйЗаказПоставщику.Товары КАК ТЧ_Товары
ГДЕ
ТЧ_Товары.Ссылка = &Ссылка) КАК Табличка
СГРУППИРОВАТЬ ПО
Табличка.Номенклатура,
Табличка.Характеристика
ИМЕЮЩИЕ
СУММА(Табличка.Количество) <> 0
Рассмотрим подробнее, как работает этот механизм:
ОтметкиСклада) с положительным числом в поле Количество.Товары), но инвертирует количество, добавляя оператор «минус» (-ТЧ_Товары.Количество).После того как запрос подготовлен, нам достаточно проверить наличие записей в его результате. Выясним, как это выглядит в модуле документа или обработки:
Запрос = Новый Запрос;
Запрос.Текст = "...(текст запроса выше)...";
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);
РезультатЗапроса = Запрос.Выполнить();
Если РезультатЗапроса.Пустой() Тогда
// Таблицы идентичны
Объект.Статус = Перечисления.СтатусыЗаказов.Закрыт;
Иначе
// Найдены расхождения
Сообщить("Обнаружены расхождения между планом и фактом поступления!");
// При необходимости можно вывести список расхождений
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.Следующий() Цикл
Сообщить("Товар: " + Выборка.Номенклатура + " Разница: " + Выборка.ПолеРазницы);
КонецЦикла;
КонецЕсли;
Рассмотрим ситуацию, которую часто обсуждают на форумах: использование ПОЛНОЕ СОЕДИНЕНИЕ. Проанализируем типичный неудачный пример кода:
// ПРИМЕР ТОГО, КАК ДЕЛАТЬ НЕ РЕКОМЕНДУЕТСЯ
ИЗ ТЧ1 ПОЛНОЕ СОЕДИНЕНИЕ ТЧ2 ПО ТЧ1.Номенклатура = ТЧ2.Номенклатура
ГДЕ ТЧ1.Количество <> ТЧ2.Количество
Проблема такого подхода:
ТЧ1 товар указан одной строкой (10 шт), а в ТЧ2 — двумя строками по 5 шт, условие 10 <> 5 сработает для каждой строки, и вы получите ложноположительный результат о наличии расхождений.ОБЪЕДИНИТЬ ВСЕ автоматически суммирует все строки перед финальным сравнением, что делает его устойчивым к способу заполнения табличных частей.При использовании данного метода важно учитывать следующие моменты:
Характеристика имеет один и тот же тип в обеих таблицах. Если в одной таблице это ссылка на справочник, а в другой поле может отсутствовать, запрос может работать некорректно.Число с большой точностью) иногда может возникать микроскопическая разница из-за особенностей хранения данных. В таких случаях в секции ИМЕЮЩИЕ вместо <> 0 можно использовать проверку на вхождение в допустимый диапазон погрешности.ОБЪЕДИНИТЬ ВСЕ, добавив соответствующие условия в ГДЕ.Таким образом, использование агрегации через объединение таблиц является наиболее профессиональным и производительным способом сравнения данных в 1С. Он позволяет быстро получить ответ на вопрос о равенстве таблиц и, при необходимости, детально расшифровать, по какой именно позиции возникло расхождение.