Posted in 1С: Предприятие 8.х Программирование

странные запросы 1Сv8

Открываю сегодня я код и как-то мозги мои начинает подклинивать:


ВЫБРАТЬ
    регСобытияОбъектов.Документ_Основание,
    регСобытияОбъектов.ВидДокумента,
    регСобытияОбъектов.ДатаЗаписи,
    регСобытияОбъектов.ЗаказДата,
    регСобытияОбъектов.ЗаказНомер,
    регСобытияОбъектов.Контрагент,
    регСобытияОбъектов.Организация,
    ВЫРАЗИТЬ(регСобытияОбъектов.Документ_Основание КАК Документ.ЭКОМ_Документы).Документ1С КАК ДокументЗаказа,
    ВЫРАЗИТЬ(регСобытияОбъектов.Документ_Основание КАК Документ.ЭКОМ_Документы).ДатаПоставки КАК ДатаПоставки,
    ВЫРАЗИТЬ(регСобытияОбъектов.Документ_Основание КАК Документ.ЭКОМ_Документы).ТочкаДоставки КАК ТочкаДоставки,
    ВЫБОР
        КОГДА регСобытияОбъектов.Статус ЕСТЬ NULL
            ТОГДА ЛОЖЬ
        ИНАЧЕ ИСТИНА
    КОНЕЦ КАК Статус_ORDER,
    регСобытияОбъектов.ТекстОшибки
ПОМЕСТИТЬ основнаяORDER
ИЗ
    РегистрСведений.СобытияОбъектов КАК регСобытияОбъектов
ГДЕ
    регСобытияОбъектов.ВидДокумента = ЗНАЧЕНИЕ(Перечисление.ВидыДокументов.ORDER_Входящий)
    И регСобытияОбъектов.ЗаказДата МЕЖДУ &ДатаНач И &ДатаКон
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    регСобытияОбъектов.ВидДокумента,
    регСобытияОбъектов.Статус,
    регСобытияОбъектов.ЗаказДата,
    регСобытияОбъектов.ЗаказНомер,
    регСобытияОбъектов.ТекстОшибки
ПОМЕСТИТЬ ОбъектыСобытияСтатус
ИЗ
    (ВЫБРАТЬ
        МАКСИМУМ(регСобытияОбъектов.ДатаЗаписи) КАК ДатаЗаписи,
        регСобытияОбъектов.ЗаказДата КАК ЗаказДата,
        регСобытияОбъектов.ЗаказНомер КАК ЗаказНомер
    ИЗ
        основнаяORDER КАК основнаяORDER
            ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СобытияОбъектов КАК регСобытияОбъектов
            ПО основнаяORDER.ЗаказДата = регСобытияОбъектов.ЗаказДата
                И основнаяORDER.ЗаказНомер = регСобытияОбъектов.ЗаказНомер
   
    СГРУППИРОВАТЬ ПО
        регСобытияОбъектов.ЗаказДата,
        регСобытияОбъектов.ЗаказНомер) КАК ОбъектыСобытия_Последние
        ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.регСобытияОбъектов КАК регСобытияОбъектов
        ПО ОбъектыСобытия_Последние.ДатаЗаписи = регСобытияОбъектов.ДатаЗаписи
            И ОбъектыСобытия_Последние.ЗаказДата = регСобытияОбъектов.ЗаказДата
            И ОбъектыСобытия_Последние.ЗаказНомер = регСобытияОбъектов.ЗаказНомер

похоже этот код сгенерирован КонструкторомЗапросов 1С. Разобравшись что же нужно получить в итоге я преобразовал этот код без вложенных запросов и странных соединеий


ВЫБРАТЬ
    СобытияОбъектов.Документ_Основание,
    СобытияОбъектов.ВидДокумента,
    СобытияОбъектов.ДатаЗаписи,
    СобытияОбъектов.ЗаказДата,
    СобытияОбъектов.ЗаказНомер,
    СобытияОбъектов.Контрагент,
    СобытияОбъектов.Организация,
    ВЫРАЗИТЬ(СобытияОбъектов.Документ_Основание КАК Документ.ЭКОМ_Документы).Документ1С КАК ДокументЗаказа,
    ВЫРАЗИТЬ(СобытияОбъектов.Документ_Основание КАК Документ.ЭКОМ_Документы).ДатаПоставки КАК ДатаПоставки,
    ВЫРАЗИТЬ(СобытияОбъектов.Документ_Основание КАК Документ.ЭКОМ_Документы).ТочкаДоставки КАК ТочкаДоставки,
    ВЫБОР
        КОГДА СобытияОбъектов.Статус ЕСТЬ NULL
            ТОГДА ЛОЖЬ
        ИНАЧЕ ИСТИНА
    КОНЕЦ КАК Статус_ORDER,
    СобытияОбъектов.ТекстОшибки
ПОМЕСТИТЬ основнаяORDER
ИЗ
    РегистрСведений.СобытияОбъектов КАК СобытияОбъектов
ГДЕ
    СобытияОбъектов.ВидДокумента = ЗНАЧЕНИЕ(Перечисление.ВидыДокументов.ORDER_Входящий)
    И СобытияОбъектов.ЗаказДата МЕЖДУ &ДатаНач И &ДатаКон
;
////////////////////////////////////////////////////////////////////////////////
ВЫБРАТЬ РАЗЛИЧНЫЕ
    СобытияОбъектов.ВидДокумента,
    МАКСИМУМ(СобытияОбъектов.ДатаЗаписи) КАК ДатаЗаписи,
    СобытияОбъектов.Статус,
    СобытияОбъектов.ЗаказДата,
    СобытияОбъектов.ЗаказНомер,
    СобытияОбъектов.ТекстОшибки
//ПОМЕСТИТЬ ОбъектыСобытияСтатус
ИЗ
    основнаяORDER КАК основнаяORDER
   
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СобытияОбъектов КАК СобытияОбъектов
    ПО основнаяORDER.ЗаказДата = СобытияОбъектов.ЗаказДата
     И основнаяORDER.ЗаказНомер = СобытияОбъектов.ЗаказНомер
     И основнаяORDER.ВидДокумента = ЗНАЧЕНИЕ(Перечисление.ВидыДокументов.ORDER_Входящий)

СГРУППИРОВАТЬ ПО
    СобытияОбъектов.ВидДокумента,
    СобытияОбъектов.Статус,
    СобытияОбъектов.ЗаказДата,
    СобытияОбъектов.ЗаказНомер,
    СобытияОбъектов.ТекстОшибки

Обратите внимание, здесь нужно лишь ЛЕВОЕ СОЕДИНЕНИЕ без вложенных подзапросов. Фактически я отбираю еще раз по той же таблице последние даты а затем к ним присоединяю необходимые последние значения. Последними они становятся т.к. я группирую поля и делаю функцию МАКСИМУМ() во 2м запросе.

Это изменение ускорило запрос на 20%

ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.СобытияОбъектов КАК СобытияОбъектов
ПО основнаяORDER.ЗаказДата = СобытияОбъектов.ЗаказДата
И основнаяORDER.ЗаказНомер = СобытияОбъектов.ЗаказНомер
И основнаяORDER.ВидДокумента = ЗНАЧЕНИЕ(Перечисление.ВидыДокументов.ORDER_Входящий)

Обратите внимание что обращение к составным реквизитам нужно делать через ВЫРАЗИТЬ() явно указывая какого типа этот реквизит.

ВЫРАЗИТЬ(регСобытияОбъектов.ДокументОснование КАК Документ.ЭКОМДокументы).Документ1С

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

Posted in 1С: Предприятие 8.х

ДанныеФормыДерево ЗначениеВДанныеФормы недопустимое значение параметра (параметр номер ‘2’) УФ

Разрабатывая в режиме совместимости интерфейса 1C 8.2 столкнулся с тем, что на УФ ЗначениеВРеквизитФормы() выдает ошибку когда пытаешься загрузить пустое ДеревоЗначений в РеквизитФормы типа ДанныеФормыДерево

Решением считаю выгружать только те колонки дерева значений в элемент формы которые есть в этом элементе.

Также я рекомендую проверять что в загружаемом в данные формы ДеревеЗначений есть колонки и какие-либо данные т.к. старые версии 1С предприятия и режимы совместимости с ними выдают ошибки, когда грузишь структуру отличную от той, то есть в элементе формы.

Ниже код для добавления в свои фреймворки.


Процедура ВыгрузитьСтрокиЭлементаДереваЗначений(Источник, Приемник, ИменаКолонокДляКопирования) Экспорт
    ВложенныеСтроки = Источник.Строки;
   
    Приемник = Новый ДеревоЗначений;
    Для каждого СтрокаИсточник Из ВложенныеСтроки Цикл
        СтрокаПриемник = Приемник.Строки.Добавить();
        ВыгрузитьСтрокиЭлементаДереваЗначений(СтрокаИсточник, СтрокаПриемник, ИменаКолонокДляКопирования);
    КонецЦикла;
   
КонецПроцедуры

Процедура СкопироватьСовпадающиеКолонкиВРезультат(Источник, Приемник) Экспорт
    Если НЕ (ТипЗнч(Источник) = Тип("ДеревоЗначений") И ТипЗнч(Приемник) = Тип("ДеревоЗначений")) Тогда
        Возврат;
    КонецЕсли;
   
    Источник = Новый ДеревоЗначений;
   
    ВсеКолонкиИсточника = Источник.Колонки;
    ВсеКолонкиПриемника = Приемник.Колонки;
   
    КолонкиДляКопирования = Новый Массив;
    Для каждого КолонкаИсточник Из ВсеКолонкиИсточника Цикл
        ИмяКолонки = КолонкаИсточник.Имя;
        ТипКолонки = КолонкаИсточник.ТипЗначения;
       
        ТакаяЖеКолонкаПриемник = ВсеКолонкиПриемника.Найти(ИмяКолонки);
       
        Если ТакаяЖеКолонкаПриемник <> Неопределено И ТипЗнч(ТакаяЖеКолонкаПриемник.ТипЗначения) Тогда
            КолонкиДляКопирования.Добавить(ИмяКолонки);
        КонецЕсли;
    КонецЦикла;
    Если КолонкиДляКопирования.Количество() = 0 Тогда
        Источник = Приемник.Скопировать();
        Источник.Строки.Очистить();
    Иначе
        ВыгрузитьСтрокиЭлементаДереваЗначений(Источник, Приемник, КолонкиДляКопирования);
    КонецЕсли;
КонецПроцедуры //СкопироватьСовпадающиеКолонкиВРезультат()

Функция ПопыткаЗначениеВРеквизитФормы(Источник, Приемник)
    Если ЗначениеЗаполнено(Источник) Тогда
        Попытка
            ЗначениеВРеквизитФормы(Источник, Приемник);          
        Исключение
            ПриемникРезультат = РеквизитФормыВЗначение(Приемник, Тип("ДеревоЗначений"));
            СкопироватьСовпадающиеКолонкиВРезультат(Источник, ПриемникРезультат);
            ЗначениеВРеквизитФормы(ПриемникРезультат, Приемник);
            //ОписаниеОшибки()
        КонецПопытки;
    КонецЕсли;
   
КонецФункции