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