Добрый день БП 3.0

 есть ТЗ с 3 колонками
НомерВходящегоДокумента
ДатаВходящегоДокумента
Сумма

в тз будет каждый раз около 3000 записей

Нужно сравнить По дате и номеру есть ли такой документ в поступление товаров или нет если нет то выдать сообщение и сравнить суммы в документе и в тз и тоже вывести сообщение
Подскажите как правильно сделать?
---
Выполнить()
для начала, есть метод проверяющий есть ли какой результат запроса

```1c
    Если Запрос.Выполнить().Пустой() Тогда
    Сообщить (" Не смогли найти документ "+стр.Накладная+" от "+стр.ДатаНакладной);
    КонецЕсли;
```

Можно было бы сделать простенький вариант так:

```1c
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
    | ПоступлениеТоваровУслуг.НомерВходящегоДокумента КАК НомерВходящегоДокумента,
    | ПоступлениеТоваровУслуг.ДатаВходящегоДокумента КАК ДатаВходящегоДокумента,
    | ПоступлениеТоваровУслуг.СуммаДокумента КАК СуммаДокумента
    |ИЗ
    | Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
    |ГДЕ
    | ПоступлениеТоваровУслуг.Дата МЕЖДУ &ДатаНачала И &ДатаКонец
    | И НЕ ПоступлениеТоваровУслуг.ПометкаУдаления";
    // Можно заменить на условие "Проведен", если нужно проверять только проведенные документы

    // получим все документы за год
    Запрос.УстановитьПараметр("ДатаНачала", НачалоГода(ТекущаяДата()));
    Запрос.УстановитьПараметр("ДатаКонец", КонецГода(ТекущаяДата()));

    ТаблицаПТиУЗаГод = Запрос.Выполнить().Выгрузить();

    Для каждого стр Из Объект.ТаблицаНоменклатуры Цикл

    НайденнаяСтрока = ТаблицаПТиУЗаГод.НайтиСтроки(Новый Структура("ДатаВходящегоДокумента,НомерВходящегоДокумента", стр.ДатаНакладной, стр.Накладная));
    Если НайденнаяСтрока.Количество() = 0 Тогда
    Сообщить (" Не смогли найти документ "+стр.Накладная+" от "+);
    Иначе
    Если НайденнаяСтрока[0].СуммаДокумента <> стр.СуммаОпт Тогда
    Сообщить ("Сумма по документу номер:"+стр.Накладная+" от "+стр.ДатаНакладной+" расходится с ПО. В 1С: "+НайденнаяСтрока[0].СуммаДокумента+" в ПО: "+стр.СуммаОпт);
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
```

Этот вариант не самый правильный, но простой для понимания. Запрос выполняется 1 раз, выгружается в таблицу. Дальше мы ищем в ней уже строчки.
---
Может сперва сделать хоть как-то, например, через цикл по тз, а потом узнать, есть ли способ лучше ?
Можно передать всю тз во временную таблицу запроса, отобрать все поступления за период во временную таблицу, либо сразу соединить во втором пакете соединить тз с поступлениями левым соединением, и отобрать где ссылка есть null.
Можно еще поиграться с индексами в запросе/тз и замерить разницу по времени.
---
да циклом тупеньким сделал работает но так очень уж долго

```1c
    Для каждого стр Из Объект.ТаблицаНоменклатуры цикл

    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
    | ПоступлениеТоваровУслуг.НомерВходящегоДокумента КАК НомерВходящегоДокумента,
    | ПоступлениеТоваровУслуг.ДатаВходящегоДокумента КАК ДатаВходящегоДокумента,
    | ПоступлениеТоваровУслуг.СуммаДокумента КАК СуммаДокумента
    |ИЗ
    | Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
    |ГДЕ
    | ПоступлениеТоваровУслуг.НомерВходящегоДокумента = &НомерВходящегоДокумента
    | И ПоступлениеТоваровУслуг.ДатаВходящегоДокумента = &ДатаВходящегоДокумента";

    Запрос.УстановитьПараметр("ДатаВходящегоДокумента", стр.ДатаНакладной);
    Запрос.УстановитьПараметр("НомерВходящегоДокумента", стр.Накладная);

    РезультатЗапроса = Запрос.Выполнить().Выбрать().Количество();

    Если Запрос.Выполнить().Выбрать().Количество() =0 Тогда
    Сообщить (" Не смогли найти документ "+стр.Накладная+" от "+стр.ДатаНакладной);
    Иначе
    Если Запрос.Выполнить().выгрузить()[0].СуммаДокумента <> стр.СуммаОпт Тогда

    Сообщить ("Сумма по документу номер:"+стр.Накладная+" от "+стр.ДатаНакладной+" расходится с ПО. В 1С"+Запрос.Выполнить().выгрузить()[0].СуммаДокумента+" в ПО"+стр.СуммаОпт);

    КонецЕсли; КонецЕсли;

    КонецЦикла;
```
---
запрос в цикле это жестоко.

Нормализовать ТЗ. Передать его в запрос во временную таблицу. Проиндексировать. Присоединить левым соединением таблицу документов поступления с соединением по номеру и даты. Желательно ограничить выборку из таблицы документов поступления (хотя бы по актуальному году).
---
Выполнить()
для начала, есть метод проверяющий есть ли какой результат запроса

```1c
    Если Запрос.Выполнить().Пустой() Тогда
    Сообщить (" Не смогли найти документ "+стр.Накладная+" от "+стр.ДатаНакладной);
    КонецЕсли;
```

Можно было бы сделать простенький вариант так:

```1c
    Запрос = Новый Запрос;
    Запрос.Текст =
    "ВЫБРАТЬ
    | ПоступлениеТоваровУслуг.Ссылка КАК Ссылка,
    | ПоступлениеТоваровУслуг.НомерВходящегоДокумента КАК НомерВходящегоДокумента,
    | ПоступлениеТоваровУслуг.ДатаВходящегоДокумента КАК ДатаВходящегоДокумента,
    | ПоступлениеТоваровУслуг.СуммаДокумента КАК СуммаДокумента
    |ИЗ
    | Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
    |ГДЕ
    | ПоступлениеТоваровУслуг.Дата МЕЖДУ &ДатаНачала И &ДатаКонец
    | И НЕ ПоступлениеТоваровУслуг.ПометкаУдаления";
    // Можно заменить на условие "Проведен", если нужно проверять только проведенные документы

    // получим все документы за год
    Запрос.УстановитьПараметр("ДатаНачала", НачалоГода(ТекущаяДата()));
    Запрос.УстановитьПараметр("ДатаКонец", КонецГода(ТекущаяДата()));

    ТаблицаПТиУЗаГод = Запрос.Выполнить().Выгрузить();

    Для каждого стр Из Объект.ТаблицаНоменклатуры Цикл

    НайденнаяСтрока = ТаблицаПТиУЗаГод.НайтиСтроки(Новый Структура("ДатаВходящегоДокумента,НомерВходящегоДокумента", стр.ДатаНакладной, стр.Накладная));
    Если НайденнаяСтрока.Количество() = 0 Тогда
    Сообщить (" Не смогли найти документ "+стр.Накладная+" от "+);
    Иначе
    Если НайденнаяСтрока[0].СуммаДокумента <> стр.СуммаОпт Тогда
    Сообщить ("Сумма по документу номер:"+стр.Накладная+" от "+стр.ДатаНакладной+" расходится с ПО. В 1С: "+НайденнаяСтрока[0].СуммаДокумента+" в ПО: "+стр.СуммаОпт);
    КонецЕсли;
    КонецЕсли;
    КонецЦикла;
```

Этот вариант не самый правильный, но простой для понимания. Запрос выполняется 1 раз, выгружается в таблицу. Дальше мы ищем в ней уже строчки.
---
А запросом через вт так ? только так получается сначала 1 запрос чтоб проверить документ есть или нет а потом еще один запрос чтоб проверить сумму правильно??

```1c
    ВЫБРАТЬ
    ТЗНомераДаты.Накладная КАК Накладная,
    ТЗНомераДаты.ДатаНакладной КАК ДатаНакладной,
    ТЗНомераДаты.СуммаОпт КАК СуммаОпт
    ПОМЕСТИТЬ ВТНомераДаты
    ИЗ
    &ТЗНомераДаты КАК ТЗНомераДаты

    ИНДЕКСИРОВАТЬ ПО
    Накладная,
    ДатаНакладной
    ;

    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ВТНомераДаты.Накладная КАК Накладная,
    ВТНомераДаты.ДатаНакладной КАК ДатаНакладной,
    ВТНомераДаты.СуммаОпт КАК СуммаОпт,
    ПоступлениеТоваровУслуг.СуммаДокумента КАК СуммаДокумента,
    ПоступлениеТоваровУслуг.Ссылка КАК Ссылка
    ПОМЕСТИТЬ ВТИтог
    ИЗ
    ВТНомераДаты КАК ВТНомераДаты
    ЛЕВОЕ СОЕДИНЕНИЕ Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТоваровУслуг
    ПО ВТНомераДаты.Накладная = ПоступлениеТоваровУслуг.НомерВходящегоДокумента
    И ВТНомераДаты.ДатаНакладной = ПоступлениеТоваровУслуг.ДатаВходящегоДокумента
    ;

    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ВТИтог.Накладная КАК Накладная,
    ВТИтог.ДатаНакладной КАК ДатаНакладной,
    ВТИтог.СуммаОпт КАК СуммаОпт,
    ВТИтог.СуммаДокумента КАК СуммаДокумента,
    ВТИтог.Ссылка КАК Ссылка
    ИЗ
    ВТИтог КАК ВТИтог
    ГДЕ
    ВТИтог.Ссылка ЕСТЬ NULL
```
---
добавьте во втором пакете поле "выбор когда ЕстьNULL(ПоступлениеТоваровУслуг.СуммаДокумента,0) = ВТНомераДаты.СуммаОпт Тогда Истина Иначе Ложь Конец как СовпадаетСумма"
а в третьем уже проверьте

```1c
    ГДЕ
    ВТИтог.Ссылка ЕСТЬ NULL ИЛИ Не СовпадаетСумма
```
 и дальше в цикле обыгрываете этот момент (предварительно вытащив это поле в третий пакет)

Так по наличию ссылки, вы поймете, что есть док, но не совпадает сумма.. а если нет, то дока просто нет
---
Индексы по ТЗ забыли.
---
+100500 оптимизация - это потом
Может сперва сделать хоть как-то, например, через цикл по тз, а потом узнать, есть ли способ лучше ?
---
https://infostart.ru/public/371762/

```1c
    // Функция НайтиПоУсловию для отбора строк в ТЗ по различным условиям
    //К сожалению в 1С нет ни лямбд ни делегатов
    //но есть функция вычислить, которая выполняет текст

    // Примеры использования
    //тз=НайтиПоУсловию(тз,"Стр.Колонка1<20 и Стр.Колонка2>500");
    // или
    //Список=ОбщегоНазначение.РазложитьСтрокуВМассивПодстрок("Иванов,Сидоров,Петров");

    //Рез=НайтиПоУсловию(тз,"Список.Найти(стр.ФизЛицо)<>Неопределено");

    //Или

    //Рез=НайтиПоУсловию(тз,"Найти(Врег(стр.Значение),Врег("акф"))>0");

    //Рез=НайтиПоУсловию(тз,"Модуль.ФункцияСравнения(Стр,Список)",МассивСтруктур,ЭтотОбъект);

    //То есть в модуле обработки должна быть функция
    // Функция ФункцияСравнения(стр,МассивСтруктур) Экспорт

    Функция НайтиПоУсловию(Тз,Условие,Список=",Модуль=") Экспорт
    Массив = новый массив;
    Для каждого Стр из Тз Цикл
    Если Вычислить(Условие) Тогда
    массив.Добавить(стр)
    КонецЕсли
    КонецЦикла;
    возврат Тз.Скопировать(массив)
    КонецФункции
```