Дорабатывал на днях типовой отчет "Остатки и доступность товаров" в конфигурации "1С:ERP Управление предприятием 2" и столкнулся с ситуацией, когда один из запросов, формирующих временные таблицу "ЗапасыИПотребности" в условии ГДЕ имеет значение ЛОЖЬ. То есть заранее обозначено, что данные получены не будут, и временная таблица будет в результате пуста. Подобная ситуация хорошо разобрана для RLS.
Для того, чтобы понять, зачем так сделано в СКД, обратимся к процедуре "ПриКомпоновкеРезультата" модуля отчета.
С самого начала видно, что от стандартных (платформенных) действий разработчики отчета отказываются и планируют формировать отчет программным образом. Далее по тексту кода видно, что вызывается некая процедура по формированию текста запроса остатков.
Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка = Ложь;
. . .
ПодставитьТекстыЗапросаОстатков(СхемаКомпоновкиДанных);
ТекстЗапроса = СхемаКомпоновкиДанных.НаборыДанных.Основной.Запрос;
. . .
КонецПроцедуры
Разберём процедуру "ПодставитьТекстыЗапросаОстатков". Вначале из макета СКД, переданного в процедуру в качестве параметра, получается текст запроса набора данных.
ТекстЗапроса = Макет.НаборыДанных[0].Запрос;
Далее в данном тексте находят формирование временной таблицы "ЗапасыИПотребности" и раздел индексации этой временной таблицы.
СтрокаДляПоиска = "ПОМЕСТИТЬ ЗапасыИПотребности";
НачальнаяПозиция = СтрНайти(ТекстЗапроса, СтрокаДляПоиска);
СтрокаДляПоиска = "ИНДЕКСИРОВАТЬ ПО";
НачальнаяПозиция = СтрНайти(ТекстЗапроса, СтрокаДляПоиска, , НачальнаяПозиция);
Создаётся массив, в который помещается часть текста запроса до индексации временной таблицы.
Тексты = Новый Массив();
Тексты.Добавить(Лев(ТекстЗапроса, НачальнаяПозиция - 1));
В зависимости от настроек конфигурации в переменную помещают РЕАЛЬНЫЙ запрос - тот, который и должен вернуть необходимые данные. Это может быть и обращение к регистру сведений, и к регистру накопления, и к регистру бухгалтерии или к внешним источникам данных. А можно обратиться и ко всем вышеперечисленным хранилищам информации.
Если ОбеспечениеВДокументахСервер.ЭтоПроизводительныйРежим() Тогда
Текст =
"ВЫБРАТЬ
| . . .
|ИЗ
| РегистрНакопления.ЗапасыИПотребности.Остатки
| . . .
|";
Иначе
Текст =
"ВЫБРАТЬ
| . . .
|ИЗ
| РегистрСведений.РаспределениеЗапасов
| . . .
|";
КонецЕсли;
Главное, чтобы колонки формируемого запроса, их порядок и тип значений совпадали с таблицей полученной в запросе с конструкцией "ГДЕ ЛОЖЬ".
Следующим шагом в массив текстов добавляется "разделитель таблиц" - конструкция ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ с пробелами до и после конструкции
Тексты.Добавить(ОбщегоНазначенияУТ.РазделительЗапросовВОбъединении());
Функция общего модуля возвращает строковое значения "разделителя таблиц":
Функция РазделительЗапросовВОбъединении(ТолькоУникальные = Ложь) Экспорт
Если ТолькоУникальные Тогда
Возврат "
|
|ОБЪЕДИНИТЬ
|
|";
Иначе
Возврат "
|
|ОБЪЕДИНИТЬ ВСЕ
|
|";
КонецЕсли;
КонецФункции
Далее в массив добавляется текст нового запроса, часть текста запроса полученного из набора данных СКД, следующего с момента индексации временной таблицы "ЗапасыИПотребности" и всё это соединяется в единый текст запроса, передаваемый в набор данных СКД.
Тексты.Добавить(Текст);
Тексты.Добавить(Сред(ТекстЗапроса, НачальнаяПозиция));
ТекстЗапроса = СтрСоединить(Тексты);
Макет.НаборыДанных[0].Запрос = ТекстЗапроса;
Окончательный вариант процедуры, подставляющий текст запроса, который позволит получить необходимые данные и передать их дальше в последующие запросы, представлен ниже.
Процедура ПодставитьТекстыЗапросаОстатков(Макет)
ТекстЗапроса = Макет.НаборыДанных[0].Запрос;
СтрокаДляПоиска = "ПОМЕСТИТЬ ЗапасыИПотребности";
НачальнаяПозиция = СтрНайти(ТекстЗапроса, СтрокаДляПоиска);
СтрокаДляПоиска = "ИНДЕКСИРОВАТЬ ПО";
НачальнаяПозиция = СтрНайти(ТекстЗапроса, СтрокаДляПоиска, , НачальнаяПозиция);
Тексты = Новый Массив();
Тексты.Добавить(Лев(ТекстЗапроса, НачальнаяПозиция - 1));
Если ОбеспечениеВДокументахСервер.ЭтоПроизводительныйРежим() Тогда
Текст =
"ВЫБРАТЬ
| ИнформацияОДоступности.Номенклатура КАК Номенклатура,
| ИнформацияОДоступности.Характеристика КАК Характеристика,
| ИнформацияОДоступности.Склад КАК Склад,
| ИнформацияОДоступности.Назначение КАК Назначение,
| ИнформацияОДоступности.Заказ КАК Заказ,
| ИнформацияОДоступности.ДатаСобытия КАК ДатаСобытия,
| ИнформацияОДоступности.ВНаличииОстаток КАК ВНаличииОстаток,
| ИнформацияОДоступности.ПоступитОстаток КАК ПоступитОстаток
|ИЗ
| РегистрНакопления.ЗапасыИПотребности.Остатки(,
| Склад ССЫЛКА Справочник.Склады
| И ВЫБОР
| КОГДА &ПоказатьОбособленныеТовары
| ТОГДА
| ИСТИНА
| ИНАЧЕ Назначение = ЗНАЧЕНИЕ(Справочник.Назначения.ПустаяСсылка)
| КОНЕЦ
| {(Номенклатура, Характеристика) В(
| ВЫБРАТЬ
| ТаблицаОтбора.Номенклатура КАК Номенклатура,
| ТаблицаОтбора.Характеристика КАК Характеристика
| ИЗ
| ОтборПоСегментуНоменклатуры КАК ТаблицаОтбора
| ГДЕ
| ТаблицаОтбора.ИспользуетсяОтборПоСегментуНоменклатуры = &ИспользуетсяОтборПоСегментуНоменклатуры)}
| {Номенклатура.* КАК Номенклатура,
| Характеристика.* КАК Характеристика,
| Склад.* КАК Склад}) КАК ИнформацияОДоступности
|";
Иначе
Текст =
"ВЫБРАТЬ
| ИнформацияОДоступности.Номенклатура КАК Номенклатура,
| ИнформацияОДоступности.Характеристика КАК Характеристика,
| ИнформацияОДоступности.Склад КАК Склад,
| ИнформацияОДоступности.Назначение КАК Назначение,
| ИнформацияОДоступности.ЗаказНаПоступление КАК Заказ,
| ИнформацияОДоступности.ДатаПоступления КАК ДатаСобытия,
| ВЫБОР
| КОГДА ИнформацияОДоступности.Состояние = ЗНАЧЕНИЕ(Перечисление.РаспределениеЗапасовСостояния.ОстатокНаСкладе)
| ТОГДА ИнформацияОДоступности.Запас
| ИНАЧЕ 0
| КОНЕЦ КАК ВНаличииОстаток,
| ВЫБОР
| КОГДА ИнформацияОДоступности.Состояние = ЗНАЧЕНИЕ(Перечисление.РаспределениеЗапасовСостояния.ОжидаемоеПоступление)
| ТОГДА ИнформацияОДоступности.Запас
| ИНАЧЕ 0
| КОНЕЦ КАК ПоступитОстаток
|ИЗ
| РегистрСведений.РаспределениеЗапасов КАК ИнформацияОДоступности
| {ВНУТРЕННЕЕ СОЕДИНЕНИЕ ОтборПоСегментуНоменклатуры КАК ТаблицаОтбора
| ПО ТаблицаОтбора.Номенклатура = ИнформацияОДоступности.Номенклатура
| И ТаблицаОтбора.Характеристика = ИнформацияОДоступности.Характеристика}
|ГДЕ
| ИнформацияОДоступности.Состояние В (
| ЗНАЧЕНИЕ(Перечисление.РаспределениеЗапасовСостояния.ОстатокНаСкладе),
| ЗНАЧЕНИЕ(Перечисление.РаспределениеЗапасовСостояния.ОжидаемоеПоступление))
| И ИнформацияОДоступности.Запас <> 0
| И ИнформацияОДоступности.Склад ССЫЛКА Справочник.Склады
| И ВЫБОР
| КОГДА &ПоказатьОбособленныеТовары ТОГДА
| ИСТИНА
| ИНАЧЕ
| ИнформацияОДоступности.Назначение = ЗНАЧЕНИЕ(Справочник.Назначения.ПустаяСсылка)
| КОНЕЦ
|{ГДЕ
| ТаблицаОтбора.ИспользуетсяОтборПоСегментуНоменклатуры = &ИспользуетсяОтборПоСегментуНоменклатуры
|}
|{ГДЕ
| ИнформацияОДоступности.Склад.* КАК Склад,
| ИнформацияОДоступности.Номенклатура.* КАК Номенклатура,
| ИнформацияОДоступности.Характеристика.* КАК Характеристика}
|";
КонецЕсли;
Тексты.Добавить(ОбщегоНазначенияУТ.РазделительЗапросовВОбъединении());
Тексты.Добавить(Текст);
Тексты.Добавить(Сред(ТекстЗапроса, НачальнаяПозиция));
ТекстЗапроса = СтрСоединить(Тексты);
Макет.НаборыДанных[0].Запрос = ТекстЗапроса;
КонецПроцедуры
Подводя общий итог, можно сказать, что использование конструкции "ГДЕ ЛОЖЬ" в тексте запроса набора данных СКД подразумевает резервирование (или бронирование) места для вставки текста запроса в зависимости от настроек или алгоритма, при этом использование результата временной таблицы уже заранее описано далее по тексту запроса.