Здравствуйте, написал отчет на СКД, протестировал в тестовой файловой базе. Все устроило, результат получился в точности соответствующий ожиданиям. Пошел ставить отчет на сервер и столкнулся с тем, что на нем отчет вообще не формируется (зависает при выполнении). Знаю, что запрос нужно как-то оптимизировать, подскажите, как.

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

Также работу может замедлить то, что в отчете на группировку "НоменклатураАналоги", накладываю отбор, что номенклатура заполнена. Нужно это для красоты, чтобы убрать вывод пустых строк под той номенклатурой, для которой нет аналогов. (даже если убрать - отчет не формируется)

```1c
    ВЫБРАТЬ
    ОстаткиИОборотыТоваров.Номенклатура КАК НоменклатураОстатки,
    ГруппыАналогов.ИдентификаторГруппы КАК ИдентификаторГруппыОстатки,
    ОстаткиИОборотыТоваров.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстатокОстатки,
    ОстаткиИОборотыТоваров.РезервКонечныйОстаток КАК РезервКонечныйОстатокОстатки,
    ОстаткиИОборотыТоваров.КоличествоКонечныйОстаток - ОстаткиИОборотыТоваров.РезервКонечныйОстаток КАК СвободныйОстатокОстатки,
    ЦеныСрезПоследних.Цена КАК ЦенаОстатки,
    ОстаткиИОборотыТоваров.СкладКомпании КАК СкладКомпании,
    ОстаткиИОборотыТоваров.СкладКомпании.Организация КАК СкладКомпанииОрганизация
    ПОМЕСТИТЬ НоменклатураСОстатками
    ИЗ
    РегистрНакопления.ОстаткиТоваровКомпании.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, Движения, ) КАК ОстаткиИОборотыТоваров
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ГруппыАналогов КАК ГруппыАналогов
    ПО ОстаткиИОборотыТоваров.Номенклатура.Артикул = ГруппыАналогов.АртикулДляПоиска
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(
    &Период,
    ПодразделениеКомпании = &ПодразделениеКомпании
    И ТипЦен = &ТипЦен) КАК ЦеныСрезПоследних
    ПО ОстаткиИОборотыТоваров.Номенклатура = ЦеныСрезПоследних.Номенклатура;

    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ГруппыАналогов.ИдентификаторГруппы КАК ИдентификаторГруппыАналоги,
    ОстаткиТоваровКомпанииОстатки.Номенклатура КАК НоменклатураАналоги,
    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток КАК КоличествоОстатокАналоги,
    ОстаткиТоваровКомпанииОстатки.РезервОстаток КАК РезервОстатокАналоги,
    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток - ОстаткиТоваровКомпанииОстатки.РезервОстаток КАК СвободныйОстатокАналоги,
    ЦеныСрезПоследних.Цена КАК ЦенаАналоги
    ПОМЕСТИТЬ АналогиСОстатками
    ИЗ
    РегистрСведений.ГруппыАналогов КАК ГруппыАналогов
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваровКомпании.Остатки(, ) КАК ОстаткиТоваровКомпанииОстатки
    ПО ГруппыАналогов.АртикулДляПоиска = ОстаткиТоваровКомпанииОстатки.Номенклатура.Артикул
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(
    &Период,
    ПодразделениеКомпании = &ПодразделениеКомпании
    И ТипЦен = &ТипЦен) КАК ЦеныСрезПоследних
    ПО ГруппыАналогов.АртикулДляПоиска = ЦеныСрезПоследних.Номенклатура.Артикул
    ГДЕ
    ОстаткиТоваровКомпанииОстатки.Номенклатура.Артикул = ГруппыАналогов.Артикул
    ;

    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    НоменклатураСОстатками.НоменклатураОстатки КАК НоменклатураОстатки,
    НоменклатураСОстатками.ИдентификаторГруппыОстатки КАК ИдентификаторГруппыОстатки,
    НоменклатураСОстатками.КоличествоКонечныйОстатокОстатки КАК КоличествоКонечныйОстатокОстатки,
    НоменклатураСОстатками.РезервКонечныйОстатокОстатки КАК РезервКонечныйОстатокОстатки,
    НоменклатураСОстатками.СвободныйОстатокОстатки КАК СвободныйОстатокОстатки,
    НоменклатураСОстатками.ЦенаОстатки КАК ЦенаОстатки,
    АналогиСОстатками.ИдентификаторГруппыАналоги КАК ИдентификаторГруппыАналоги,
    АналогиСОстатками.НоменклатураАналоги КАК НоменклатураАналоги,
    АналогиСОстатками.КоличествоОстатокАналоги КАК КоличествоОстатокАналоги,
    АналогиСОстатками.РезервОстатокАналоги КАК РезервОстатокАналоги,
    АналогиСОстатками.СвободныйОстатокАналоги КАК СвободныйОстатокАналоги,
    АналогиСОстатками.ЦенаАналоги КАК ЦенаАналоги,
    НоменклатураСОстатками.СкладКомпании КАК СкладКомпании,
    НоменклатураСОстатками.СкладКомпанииОрганизация КАК СкладКомпанииОрганизация
    {ВЫБРАТЬ
    НоменклатураОстатки.*,
    ИдентификаторГруппыОстатки,
    КоличествоКонечныйОстатокОстатки,
    РезервКонечныйОстатокОстатки,
    СвободныйОстатокОстатки,
    ЦенаОстатки,
    ИдентификаторГруппыАналоги,
    НоменклатураАналоги.*,
    КоличествоОстатокАналоги,
    РезервОстатокАналоги,
    СвободныйОстатокАналоги,
    ЦенаАналоги,
    СкладКомпании.*,
    СкладКомпанииОрганизация.* КАК Организация}
    ИЗ
    НоменклатураСОстатками КАК НоменклатураСОстатками
    ЛЕВОЕ СОЕДИНЕНИЕ АналогиСОстатками КАК АналогиСОстатками
    ПО НоменклатураСОстатками.ИдентификаторГруппыОстатки = АналогиСОстатками.ИдентификаторГруппыАналоги
    {ГДЕ
    НоменклатураСОстатками.НоменклатураОстатки.*,
    АналогиСОстатками.НоменклатураАналоги.*,
    НоменклатураСОстатками.СкладКомпании.*,
    НоменклатураСОстатками.СкладКомпанииОрганизация.* КАК Организация}
```
---
если почитать методички 1с (да кто ж их читает-то?), то там русским по белому написано, что с виртуальными таблицами соединения это непроизводительно.
Тут еще и по реквизиту реквизита соединение. Представь размер таблицы, которую генерирует СУБД, чтобы получить результат такого соединения...
А в первом запросе мы выбираем остатки и обороты, хотя зачем там обороты, так и остается неясным, они не используются
(1) РегистрНакопления.ОстаткиТоваровКомпании.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, Движения, )
Оптимизация запросов конечно вещь темная, но что-то можно попробовать. Все сложить по временным таблицам, проиндексировать их как-нибудь разумно, убрать очевидно лишние данные (например, обороты там, где они не используются)
---
Дополню (6).
1) в 1 запросе брать данные только из таблицы Остатки регистра накопления. Поместить ее во временную таблицу.
2) в следующем запросе соединять РС с таблицей остатков из п.1.
3) брать опять же таблицу из п.1, вместо повторного обращения к регистру накопления. Это те же самые данные.
---
если почитать методички 1с (да кто ж их читает-то?), то там русским по белому написано, что с виртуальными таблицами соединения это непроизводительно.
Тут еще и по реквизиту реквизита соединение. Представь размер таблицы, которую генерирует СУБД, чтобы получить результат такого соединения...
А в первом запросе мы выбираем остатки и обороты, хотя зачем там обороты, так и остается неясным, они не используются
(1) РегистрНакопления.ОстаткиТоваровКомпании.ОстаткиИОбороты(&НачалоПериода, &КонецПериода, Авто, Движения, )
Оптимизация запросов конечно вещь темная, но что-то можно попробовать. Все сложить по временным таблицам, проиндексировать их как-нибудь разумно, убрать очевидно лишние данные (например, обороты там, где они не используются)
---
Дополню (6).
1) в 1 запросе брать данные только из таблицы Остатки регистра накопления. Поместить ее во временную таблицу.
2) в следующем запросе соединять РС с таблицей остатков из п.1.
3) брать опять же таблицу из п.1, вместо повторного обращения к регистру накопления. Это те же самые данные.
---
```1c
    в 1 запросе брать данные только из таблицы Остатки регистра накопления. Поместить ее во временную таблицу.
```

(6)А в первом запросе мы выбираем остатки и обороты, хотя зачем там обороты, так и остается неясным, они не используются

От таблицы оборотов избавился - к скорости значительно это не прибавило. Она была пережитком типового отчета ОстаткиИОборотыТоваров.

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

Мне нужно получить существующие остатки номенклатуры и ее цену. Получить аналоги для этой номенклатуры со всеми остатками и ценами и вывести это. Чтобы было видно какая номенклатура в наличии (или не в наличии, кстати) и ее аналоги (с количеством и ценами)
---
как использовать Остатки в виде временной таблицы
ну хотя бы так

```1c
    РегистрСведений.ГруппыАналогов КАК ГруппыАналогов
    ЛЕВОЕ СОЕДИНЕНИЕ НоменклатураСОстатками КАК НоменклатураСОстатками
```

запрос полностью я могу написать, но это платная опция. Все советы, по-моему, выше уже изложены, надо брать и делать. Лучше в консоли запросов, которая умеет оценивать время выполнения подзапросов, тогда понятнее будет, где проблема остается.
---
ЗЫ
(10) (или не в наличии, кстати)
а это условие, между прочим, меняет ход дела совсем. В регистре остатков не найти того, чего нет. Получается, что исходный запрос был неправильный...
---
Да, тоже к такому выводу пришел. По идее нужно тогда выбрать всю номенклатуру из справочника и к ней присоединять уже цены, остатки и т. д.

Буду пробовать, спасибо!
---
ИЗ
    НоменклатураСОстатками КАК НоменклатураСОстатками
        ЛЕВОЕ СОЕДИНЕНИЕ АналогиСОстатками КАК АналогиСОстатками
итоговый запрос у нас такой. Это значит, что полный набор нужных товаров мы получаем в первом запросе. Вот если его сложить во временную таблицу и потом по ней делать все остальные отборы виртуальных таблиц, есть шанс, что все выборки сильно сократятся и всю базу не надо будет перелопачивать каждый раз... А первый запрос - заменить на остатки, т.к. кроме конечного остатка нам ничего из него не нужно вроде бы. Как-то так, наверное.
---
```1c
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваровКомпании.Остатки(, ) КАК ОстаткиТоваровКомпанииОстатки
```

ну это ж... мда. А что вы таки хотели? много остатков-то?
---
```1c
    ПО ОстаткиИОборотыТоваров.Номенклатура.Артикул = ГруппыАналогов.АртикулДляПоиска
```

А еще получение каждого объекта номенклатуры...
---
Знаю, что запрос не идеален, потому и пишу, так как не придумал, как лучше связать между собой аналоги и остатки. Связываю их по идентификатору уникальному, который указан в регистре сведений:

1. По какой-то причине разработчики не стали добавлять в регистр ссылку на номенклатуру, по которой можно было бы связаться в запросе.
2. Добавлять ссылку не вариант, так как в регистр добавить измерение через расширение платформа не дает, а лезть в конфигурацию и там добавлять мне старший не позволит (крайняя мера) :)
---
Действительно, про условия в регистре забыл, добавил еще на организацию и склад дополнительно.

```1c
    ВЫБРАТЬ
    ОстаткиИОборотыТоваров.Номенклатура КАК НоменклатураОстатки,
    ГруппыАналогов.ИдентификаторГруппы КАК ИдентификаторГруппыОстатки,
    ОстаткиИОборотыТоваров.КоличествоКонечныйОстаток КАК КоличествоКонечныйОстатокОстатки,
    ОстаткиИОборотыТоваров.РезервКонечныйОстаток КАК РезервКонечныйОстатокОстатки,
    ОстаткиИОборотыТоваров.КоличествоКонечныйОстаток - ОстаткиИОборотыТоваров.РезервКонечныйОстаток КАК СвободныйОстатокОстатки,
    ЦеныСрезПоследних.Цена КАК ЦенаОстатки,
    ОстаткиИОборотыТоваров.СкладКомпании КАК СкладКомпании,
    ОстаткиИОборотыТоваров.СкладКомпании.Организация КАК СкладКомпанииОрганизация
    ПОМЕСТИТЬ НоменклатураСОстатками
    ИЗ
    РегистрНакопления.ОстаткиТоваровКомпании.ОстаткиИОбороты(
    &НачалоПериода,
    &КонецПериода,
    Авто,
    Движения,
    СкладКомпании = &СкладКомпании
    И СкладКомпании.Организация = &Организация) КАК ОстаткиИОборотыТоваров
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ГруппыАналогов КАК ГруппыАналогов
    ПО ОстаткиИОборотыТоваров.Номенклатура.Артикул = ГруппыАналогов.АртикулДляПоиска
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(
    &Период,
    ПодразделениеКомпании = &ПодразделениеКомпании
    И ТипЦен = &ТипЦен) КАК ЦеныСрезПоследних
    ПО ОстаткиИОборотыТоваров.Номенклатура = ЦеныСрезПоследних.Номенклатура
    ;

    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    ГруппыАналогов.ИдентификаторГруппы КАК ИдентификаторГруппыАналоги,
    ОстаткиТоваровКомпанииОстатки.Номенклатура КАК НоменклатураАналоги,
    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток КАК КоличествоОстатокАналоги,
    ОстаткиТоваровКомпанииОстатки.РезервОстаток КАК РезервОстатокАналоги,
    ОстаткиТоваровКомпанииОстатки.КоличествоОстаток - ОстаткиТоваровКомпанииОстатки.РезервОстаток КАК СвободныйОстатокАналоги,
    ЦеныСрезПоследних.Цена КАК ЦенаАналоги
    ПОМЕСТИТЬ АналогиСОстатками
    ИЗ
    РегистрСведений.ГруппыАналогов КАК ГруппыАналогов
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиТоваровКомпании.Остатки(
    &КонецПериода,
    СкладКомпании = &СкладКомпании
    И СкладКомпании.Организация = &Организация) КАК ОстаткиТоваровКомпанииОстатки
    ПО ГруппыАналогов.АртикулДляПоиска = ОстаткиТоваровКомпанииОстатки.Номенклатура.Артикул
    ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.Цены.СрезПоследних(
    &Период,
    ПодразделениеКомпании = &ПодразделениеКомпании
    И ТипЦен = &ТипЦен) КАК ЦеныСрезПоследних
    ПО ГруппыАналогов.АртикулДляПоиска = ЦеныСрезПоследних.Номенклатура.Артикул
    ГДЕ
    ОстаткиТоваровКомпанииОстатки.Номенклатура.Артикул = ГруппыАналогов.Артикул
    ;

    ////////////////////////////////////////////////////////////­////////////////////
    ВЫБРАТЬ
    НоменклатураСОстатками.НоменклатураОстатки КАК НоменклатураОстатки,
    НоменклатураСОстатками.ИдентификаторГруппыОстатки КАК ИдентификаторГруппыОстатки,
    НоменклатураСОстатками.КоличествоКонечныйОстатокОстатки КАК КоличествоКонечныйОстатокОстатки,
    НоменклатураСОстатками.РезервКонечныйОстатокОстатки КАК РезервКонечныйОстатокОстатки,
    НоменклатураСОстатками.СвободныйОстатокОстатки КАК СвободныйОстатокОстатки,
    НоменклатураСОстатками.ЦенаОстатки КАК ЦенаОстатки,
    АналогиСОстатками.ИдентификаторГруппыАналоги КАК ИдентификаторГруппыАналоги,
    АналогиСОстатками.НоменклатураАналоги КАК НоменклатураАналоги,
    АналогиСОстатками.КоличествоОстатокАналоги КАК КоличествоОстатокАналоги,
    АналогиСОстатками.РезервОстатокАналоги КАК РезервОстатокАналоги,
    АналогиСОстатками.СвободныйОстатокАналоги КАК СвободныйОстатокАналоги,
    АналогиСОстатками.ЦенаАналоги КАК ЦенаАналоги,
    НоменклатураСОстатками.СкладКомпании КАК СкладКомпании,
    НоменклатураСОстатками.СкладКомпанииОрганизация КАК СкладКомпанииОрганизация
    {ВЫБРАТЬ
    НоменклатураОстатки.*,
    ИдентификаторГруппыОстатки,
    КоличествоКонечныйОстатокОстатки,
    РезервКонечныйОстатокОстатки,
    СвободныйОстатокОстатки,
    ЦенаОстатки,
    ИдентификаторГруппыАналоги,
    НоменклатураАналоги.*,
    КоличествоОстатокАналоги,
    РезервОстатокАналоги,
    СвободныйОстатокАналоги,
    ЦенаАналоги,
    СкладКомпании.*,
    СкладКомпанииОрганизация.* КАК Организация}
    ИЗ
    НоменклатураСОстатками КАК НоменклатураСОстатками
    ЛЕВОЕ СОЕДИНЕНИЕ АналогиСОстатками КАК АналогиСОстатками
    ПО НоменклатураСОстатками.ИдентификаторГруппыОстатки = АналогиСОстатками.ИдентификаторГруппыАналоги
    {ГДЕ
    НоменклатураСОстатками.НоменклатураОстатки.*,
    АналогиСОстатками.НоменклатураАналоги.*,
    НоменклатураСОстатками.СкладКомпании.*,
    НоменклатураСОстатками.СкладКомпанииОрганизация.* КАК Организация}
```

Правда отчет все равно не формируется, что-то не так сделал?

Остатков вагон и маленькая тележка, отбираю их уже по складу, группе номенклатуры, организации уже не знаю на что еще отбор добавить
---
Зачем ОстаткиИОбороты если достаточно только Остатки? И отделить получение остатков от соединений.
Впрочем вам это уже писали, но вы не прислушиваетесь к советам.
---
получение вначале общей таблицы номенклатур с аналогами а потом уже дополнить её остатками и ценами должно максимально быстрым способом.
---
Доброго дня! А SQL у вас какой на сервере крутится? Не Postgres случайно?
---
Добрый день, да, верно, на Postgress. В основном проблема была в том, что цены по более, чем десятку подразделений указаны, ограничил, запрос стал работать. Чуть позже выложу заработавший вариант
---
Postgres очень не любит ЛЕВОЕ СОЕДИНЕНИЕ ХХХ.СрезПоследних. Хотя из ИТС для последних релизов убрали эту рекомендацию, но у меня на 23 релизе, при вынесении таблицы СрезПоследних во временную, производительность запроса увеличивается очень существенно. И да, Вам правильно сказали, лучше все виртуальные таблицы (остатки, срезы), сначала поместить во временные таблицы (ВЫБРАТЬ * ПОМЕСТИТЬ ВТОстатки ИЗ ХХХ.Остатки; ВЫБРАТЬ * ПОМЕСТИТЬ ВТЦены ИЗ ХХХ.СрезПоследних), а уже затем их связывать.