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