В тестовой конфигурации у нас есть периодический регистр сведений "ЦеныНоменклатуры" со следующими исходными данными:
На рисунке представлена также структура метаданных регистра. Как мы видим, регистр содержит измерение "Товар" с типом ссылки на справочник "Товары", а также числовой ресурс "Цена" и реквизит "СтараяЦена".
Допустим, в отчете нам нужно получить срез последних записей для товаров и их цен с условием, что старая цена меньше или равно 50.
Сразу скажу, что рассматривать будем правильный и не правильный варианты.Начнем с последнего. Эту ошибку часто делают начинающие программисты. И так, для отчета был написан следующий запрос:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ | ЦеныНоменклатурыСрезПоследних.Период, | ЦеныНоменклатурыСрезПоследних.Товар, | ЦеныНоменклатурыСрезПоследних.Цена, | ЦеныНоменклатурыСрезПоследних.СтараяЦена |ИЗ | РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК ЦеныНоменклатурыСрезПоследних |ГДЕ | ЦеныНоменклатурыСрезПоследних.СтараяЦена <= 50";
Обратите внимание на условие в секции "ГДЕ". В этом и заключается главная ошибка! Этот запрос не вернет ни одной записи, и вот почему: при использовании виртуальных таблиц, в нашем случае "СрезПоследних", сначала выполняется выборка данных из базы по условиям, описанным в виртуальной таблице, а затем выполняются действия, описанные в тексте запроса (группировки, условия в секции "ГДЕ", сортировка и т.д.).
Поэтому в нашем примере запрос и не возвращает результат. Сначала он получает срез последних, а уже после устанавливает условие на реквизит "СтараяЦена". Вот так это выглядит на схеме:
Чтобы правильно решить задачу, условие на реквизит "СтараяЦена" нужно перенести в условия виртуальной таблицы. Вот так будет выглядеть правильный текст запроса:
Запрос = Новый Запрос; Запрос.Текст = "ВЫБРАТЬ ЦеныНоменклатурыСрезПоследних.Период, ЦеныНоменклатурыСрезПоследних.Товар, ЦеныНоменклатурыСрезПоследних.Цена, ЦеныНоменклатурыСрезПоследних.СтараяЦена ИЗ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, СтараяЦена <= 50) КАК ЦеныНоменклатурыСрезПоследних"
Теперь запрос получит правильные данные, поскольку срез последних цен будет получать уже с учетом условия по реквизиту "СтараяЦена".
Следует понимать, что описанное выше относится ко всем случаям использования виртуальных таблиц в запросах (для регистров накопления, регистров бухгалтерии, задач и т.д.).
Отсюда также вытекает главное правило по использованию виртуальных таблиц: "используя виртуальную таблицу обязательно устанавливайте параметры отбора непосредственно в виртуальной таблице, иначе запрос будет получать излишние данные, на которые уже потом будут устанавливаться отборы".