Нюансы преобразования запроса СКД

Описание некоторых нюансов преобразования запроса в СКД.

Попытаюсь изложить некоторые встреченные нюансы парсинга текста запроса в СКД — т.е. каким образом преобразуется в приведенных примерах текст запроса, написанный в окне Запроса закладки Наборы данных в СКД — далее просто ТЗ СКД. Для примеров используется конфигурация Управление торговлей, редакция 11.3.

Известно, что СКД создана в том числе и для минимизации действий кодировщика и проделывает за него некоторые скрытые действия, которые не всегда оказываются очевидными.

1. Поведение соединений к основной таблице 

Создаю новый внешний отчет, для него создаю основную схему компоновки данных. Пишу в ней такой  ТЗ СКД

 

 

ВЫБРАТЬ
РеализацияТоваровУслугТовары.Ссылка,
ДокРеализация.Дата,
РеализацияТоваровУслугТовары.Номенклатура,
РеализацияТоваровУслугТовары.КоличествоУпаковок,
РеализацияТоваровУслугТовары.Цена,
РеализацияТоваровУслугТовары.Сумма
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
{
внутреннее соединение Документ.РеализацияТоваровУслуг ДокРеализация по ДокРеализация.Ссылка=РеализацияТоваровУслугТовары.Ссылка
}
{где
ДокРеализация.Дата = &ДатаОтчета
}

 

Фигурные скобки в ТЗ СКД означают для соединений и условий то, что данная часть ТЗ СКД будет включаться в результирующий текст запроса только при определенных пользовательских настройках.

Для того, чтобы увидеть результат преобразования в модуле отчета создаю следующую процедуру:

Процедура ПриКомпоновкеРезультата(ДокументРезультат, ДанныеРасшифровки, СтандартнаяОбработка)
СтандартнаяОбработка=ложь;

НастройкиОтчета = КомпоновщикНастроек.ПолучитьНастройки();

КомпоновщикМакета = Новый КомпоновщикМакетаКомпоновкиДанных;
МакетКомпоновки = КомпоновщикМакета.Выполнить(СхемаКомпоновкиДанных, НастройкиОтчета, ДанныеРасшифровки);

сообщить(МакетКомпоновки.НаборыДанных.НаборДанных1.Запрос);

КонецПроцедуры

Вывожу параметр ДатаОтчета на форму, создаю простую настройку с одной группировкой "Номенклатура" без каких либо полей и запускаю формирование отчета — вначале с отключенной галочкой отбора по параметру. В окне сообщений получаю результирующий запрос, который будет использоваться системой для получения необходимых для отчета данных:

ВЫБРАТЬ
РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
ПРЕДСТАВЛЕНИЕССЫЛКИ(РеализацияТоваровУслугТовары.Номенклатура) КАК НоменклатураПредставление,
РеализацияТоваровУслугТовары.Номенклатура.Наименование КАК НоменклатураНаименование
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары

Видно, что внутреннее соединение из ТЗ СКД отсутствует, т.к. ни в фильтре, ни в полях настройки нигде эта таблица не требуется.

Если установить фильтр по дата, то получаем результирующий запрос

ВЫБРАТЬ
РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
ПРЕДСТАВЛЕНИЕССЫЛКИ(РеализацияТоваровУслугТовары.Номенклатура) КАК НоменклатураПредставление,
РеализацияТоваровУслугТовары.Номенклатура.Наименование КАК НоменклатураНаименование
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК ДокРеализация
ПО (ДокРеализация.Ссылка = РеализацияТоваровУслугТовары.Ссылка)
ГДЕ
ДокРеализация.Дата = &ДатаОтчета

Внутреннее соединение появилось. То же самое произойдет если не включать фильтр по дате, а попробовать в настройках вывести поле Дата:

ВЫБРАТЬ
ДокРеализация.Дата КАК Дата,
РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
ПРЕДСТАВЛЕНИЕССЫЛКИ(РеализацияТоваровУслугТовары.Номенклатура) КАК НоменклатураПредставление,
РеализацияТоваровУслугТовары.Номенклатура.Наименование КАК НоменклатураНаименование
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК ДокРеализация
ПО (ДокРеализация.Ссылка = РеализацияТоваровУслугТовары.Ссылка)

Теперь дописываю ТЗ СКД, включая еще одно соединение — со справочником Партнеры:

 

Текст запроса СКД

Формирую с условием по партнеру, но без условия по дате и без полей-группировок по дате в запросе. В результирующем запросе получаю не совсем то, что ожидал:

ВЫБРАТЬ
РеализацияТоваровУслугТовары.Номенклатура КАК Номенклатура,
ПРЕДСТАВЛЕНИЕССЫЛКИ(РеализацияТоваровУслугТовары.Номенклатура) КАК НоменклатураПредставление,
РеализацияТоваровУслугТовары.Номенклатура.Наименование КАК НоменклатураНаименование
ИЗ
Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары,
Справочник.Партнеры КАК СпрПартнеры
ГДЕ
СпрПартнеры.Ссылка = &П

Для избежания подобного результата нужно либо убирать фигурные скобки в первом соединении — тогда оно будет включатся в результирующий запрос всегда, либо оба соединения заключать в общие фигурные скобки — тогда оба соединения будут включены в текст запроса в случаях, когда в пользовательских настройках требуется либо получение даты либо получение партнера. Четкой рекомендации для подобных случаев дать не могу, кроме как просматривать результирующий текст запроса при отладке отчета при разных вариантах настроек.

2. Неочевидное включение фильтров

В приведенном примере требуется показать номенклатуру из документов Реализация по определенному складу и вывести дополнительно остаток по номенклатуре по всем складам суммарно. Пишу следующий ТЗ СКД:

 

Текст запроса СКД

формирую отчет с фильтром по складу и получаю результирующий запрос в таком виде:

 

 Результирующий запрос

Здесь видно, что система сама включила фильтр по складу во виртуальную таблицу остатков. Не очень ожидаемое действие. Приходится для избежания этого назначать другое имя переменной для фильтра по складу документа:

...
{где
ДокРеализация.Дата = &ДатаОтчета,
ДокРеализация.Склад.* Как СкладРеализации
}

Тогда отбор в виртуальной таблице уже отсутствует.

3. Управление формированием временных таблиц

Случается, что для организации фильтра удобно использование временных таблиц. Опишу, каким образом удобно включать/отключать формирование временной таблицы только тогда, когда она требуется по текущим настройкам пользователя. ТЗ СКД:

 

Текст запроса

Модуль отчета будет выглядеть таким образом:

 

Модуль отчета

В данном примере запрос к формирования временной таблицы ТаблицаОстаткиНоменклатуры будет выполняться при условии, когда пользователь выбирает фильтр либо по СкладОстатков, либо по Номенклатура.

4. Неожиданное в преобразовании для периодов ВТ

Как то неоднократно сталкивался, не искал, что про это пишут в документации, был бы признателен, если бы кто-нибудь указал. Пример запроса:

 

 Текст запроса

ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура,
ТоварыНаСкладахОстатки.ВНаличииОстаток
поместить ОстаткиНаДата1
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&ДатаОтчета,{Номенклатура.* как Номенклатура} ) КАК ТоварыНаСкладахОстатки
;

ВЫБРАТЬ
ТоварыНаСкладахОстатки.Номенклатура,
ОстаткиНаДата1.ВНаличииОстаток Остаток1,
ТоварыНаСкладахОстатки.ВНаличииОстаток Остаток2
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(,{Номенклатура.* как Номенклатура} ) КАК ТоварыНаСкладахОстатки

левое соединение ОстаткиНаДата1 по ОстаткиНаДата1.Номенклатура=ТоварыНаСкладахОстатки.Номенклатура

 

В параметрах у нас при этом появится предопределенный параметр "Период". Назначим на форме значения параметров Период и ДатаОтчета. В результирующем запросе получаю:

 

 Результат выполнения компоновщика макета

То есть у обеих ВТ установлен один период. И он равен параметру Период. Не поможет и то, что во второй ВТ я явно укажу Период:

...
ИЗ
РегистрНакопления.ТоварыНаСкладах.Остатки(&Период,{Номенклатура.* как Номенклатура} ) КАК ТоварыНаСкладахОстатки
...

Результат выполнения компоновщика будет тот же. Решается только в том случае, если я напишу запрос СКД таким образом:

 

 ТЗ СКД

 

 Результат, который нужен

Все получилось. Но все равно одна засада остается. Если пресловутый предопределенный параметр под названием Период все же вывести на форму и активизировать его, то при последнем варианте запроса у нас все равно старый косяк — у обеих ВТ один Период. Что тут можно посоветовать — поосторожней пользоваться предопределенным параметром Период, поскольку система так и норовит вставить его во все ВТ остатков. Аналогичное можно сказать про предопределенные параметры НачалоПериода и КонецПериода у ВТ Обороты или ОстаткиИОбороты. Я с ними тоже как то натерпелся. То есть, если виртуальных таблиц более одной и у них разные периоды, то предопределенные лучше не трогать.

14 Comments

  1. Поручик

    Будем знать

    Reply
  2. dhurricane

    Не удалось воспроизвести проблему соединения со справочником партнеров из п.1, а вернее отсутствие соединения. Быть может это ошибка платформы, на которой Вы получили такой результат? И нет, так быть не должно, СКД не требует объединять в единые фигурные скобки все присоединяемые таблицы. В конструкторе запросов на закладке «Компоновка данных Таблицы» для этого разделения предусмотрена даже отдельная колонка «Номер группы».

    Reply
  3. the1

    Что-то как-то сумбурно — ни тебе выводов, ни закономерностей. Прост я поэкспериментировал, гляньте и вы.

    Reply
  4. waol

    (2) п.1 — на платформе 8.3.10.2580. выборка



    ИЗ

    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары

    {

    внутреннее соединение Документ.РеализацияТоваровУслуг ДокРеализация по ДокРеализация.Ссылка=РеализацияТоваровУслугТовары.Ссылка

    }

    {

    левое соединение Справочник.Партнеры СпрПартнеры по СпрПартнеры.Ссылка=ДокРеализация.Партнер

    }

    преобразовывается в

    ИЗ

    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары,

    Справочник.Партнеры КАК СпрПартнеры

    проверил сейчас на 8.3.13.1690 — аналогично

    Reply
  5. dhurricane

    (4) Прошу прощения, действительно воспроизводится. Я не правильно проверял, нужно было полностью скопировать Ваш код, чтобы получить аналогичный Вашему результат.

    И здесь действительно ошибка в том, что таблицы в разных фигурных скобках. Но на мой взгляд это именно ошибка программиста, не СКД. Связь с таблицей партнеров осуществляется посредством таблицы документа реализации. Т.е. чтобы связать основную таблицу с таблицей партнеров обязательно нужна таблица реализации, поэтому разделять таблицу документа и таблицу справочника некорректно.

    Но вот если связать таблицу товаров непосредственно с таблицей партнеров (через ссылку), то никуда связь не будет пропадать.

    Reply
  6. ids79

    Добрый день.

    1. В конструкторе запроса, в расширение компоновки, при указании таблиц, как необязательные, присутствует реквизит «Номер группы». Он как раз и отвечает за то, включаются ли две разные таблицы в одну группу или в разные. В Вашем случае необходимо включить таблицы в одну группу, так как одна без другой не имеет смысла. В этом случае обе таблицы будут в одних скобках, как Вы пишете.

    2. Это стандартное поведение системы, и оно описано. При указании отбора, СКД будет пытаться применить его для всех запросов в пакете. Также, если включено автозаполнение, отбор будет применен к параметрам виртуальных таблиц, если это возможно.

    Reply
  7. VmvLer

    тема отражает некий профессиональный рост автора в познании определенных методов работы СКД и несет чисто развлекательный характер.

    спасибо всем, кто вник и придал ускорение мыслям автора.

    Reply
  8. azmievsky

    Если пытаться разбираться с СКД самостоятельно, без документации и курсов, — каждый день будешь открывать для себя все новые и новые «нюансы».

    Reply
  9. A_Max

    (5)

    (4)А вот так:

    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары

    {

    внутреннее соединение Документ.РеализацияТоваровУслуг ДокРеализация по ДокРеализация.Ссылка=РеализацияТоваровУслугТовары.Ссылка

    {

    левое соединение Справочник.Партнеры СпрПартнеры по СпрПартнеры.Ссылка=ДокРеализация.Партнер

    }}
    Reply
  10. waol

    (9)

    то же самое

    ИЗ

    Документ.РеализацияТоваровУслуг.Товары КАК РеализацияТоваровУслугТовары,

    Справочник.Партнеры КАК СпрПартнеры

    при установке фильтра только по партнеру. на 8.3.10.2580

    Reply
  11. sergey_garin

    Почему-то не написано о механизме оптимизации СКД: о том, как она иногда меняет запросы и выкидывает из них нужные поля, в результате чего результат получается совсем не тот, который ожидаешь.

    Неоднократно сталкивается с тем, что СКД удаляет из выборки те поля, которые не выводятся в табличный документ, несмотря на то, что по ним есть нужные группировки во временных таблицах.

    Reply
  12. waol

    (11) было бы интересно посмотреть на примеры, это было бы как раз по теме

    Reply
  13. Stas-ch

    (12) На вскидку — две таблицы соединяются по двум полям (Допустим контрагент и договор), однако выбирается только одно поле (к примеру, Контрагент). Вроде в этом случае объединение по договору будет исключено.

    Reply
  14. Stas-ch

    (13) В этом случае надо на закладке Наборы данных — Поля — в колонке Роль поставить флаг Обязательный.

    Reply

Leave a Comment

Ваш адрес email не будет опубликован. Обязательные поля помечены *