Форум 1С
Программистам, бухгалтерам, администраторам, пользователям
Задай вопрос - получи решение проблемы
22 ноя 2024, 23:06

Внутренне соединение вместо левого в зависимости от параметра

Автор vitasw, 18 мар 2015, 17:10

0 Пользователей и 1 гость просматривают эту тему.

vitasw

Здравствуйте. Что-то совсем завис.

Есть очень большой отчет на СКД(обычные формы). Куча вложенных запросов в результате левым соединением цепляются к справочнику номенклатуры. Как в зависимости от параметра сделать вместо левого соединения - внутреннее. Отчет формирует прайс-лист. На текущий момент формируется по всему справочнику. На форму отчета выведен признак(Булево) "По остаткам"-> чтобы не ваять новую схему СКД(это конечно вариант - но не очень комильфо) в запросе СКД вместо левого соединения каким-то волшебным образом установить внутреннее соединение.
Установить отбор на результирующую таблицу, типа "Где Остаток>0"  - не вариант из-за скорости выполнения отчета.

Т.е.

Есть

"ВЫБРАТЬ
       |    ВложенныйЗапрос.Номенклатура,
       |    ТоварыНаСкладахОстатки.КоличествоОстаток
       |ИЗ
       |    (ВЫБРАТЬ
       |        Номенклатура.Ссылка КАК Номенклатура
       |    ИЗ
       |        Справочник.Номенклатура КАК Номенклатура
       |    ГДЕ
       |        Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ВложенныйЗапрос
       |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
       |        ПО ВложенныйЗапрос.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура";

А нужно

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

в запвисимости от параметра. Повторюсь еще раз - это СКД на обычных формах.

Спасибо за любые идеи

LexaK

Совсем дурные так писать запросы?

Цитировать
       |    (ВЫБРАТЬ
       |        Номенклатура.Ссылка КАК Номенклатура
       |    ИЗ
       |        Справочник.Номенклатура КАК Номенклатура
       |    ГДЕ
       |        Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ВложенныйЗапрос
       |        ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки КАК

просто же все


       "ВЫБРАТЬ
       |    Спр.Ссылка как Номенклатура,
       |    Рег.КоличествоОстаток
       |ИЗ
       |    Справочник.Номенклатура КАК Спр
       |ЛЕВОЕ СОЕДИНЕНИЕ
       |    РегистрНакопления.ТоварыНаСкладах.Остатки КАК Рег
       |    ПО Спр.Ссылка = Рег.Номенклатура
       |ГДЕ
       |Не  Спр.ЭтоГруппа
       |и   (&ВсяНоменклатура или Рег.КоличествоОстаток Есть Не Null) 
       |";


в параметрах задаете переменную ВсяНоменклатура  - Булево, если
Истина - будет выведена вся номенклатура и кое где остатки
Ложь - будет выведена номенклатура по которой есть остатки (любые)
(остатки могут быть и отрицательными)
если нужны только положительные остатки - надо изменить условие.
если помогло нажмите: Спасибо!

vitasw

1. Я привел пример
2. Я привел промер того как уже написан очень большой запрос, и не мной. И перелапачивать две вложенные схемы СКД по 600-800 строк запроса в каждом у меня нет никакого желания.
3. Я уже писал
Цитата: vitasw от 18 мар 2015, 17:10становить отбор на результирующую таблицу, типа "Где Остаток>0"  - не вариант из-за скорости выполнения отчета.
Усливе типа "Где" никакого выиграша по скорости не дает.


LexaK

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

в запросе пишите

|   ЛЕВОЕ СОЕДИНЕНИЕ //001

затем перед выполнением отчета, в модуле

Если <ВашеУсловие> Тогда
    ТекстЗапроса = СтрЗаменить(ТекстЗапроса,
        "ЛЕВОЕ СОЕДИНЕНИЕ //001","ВНУТРЕННЕЕ СОЕДИНЕНИЕ");
КонецЕсли;


заменится только то левое соединение рядом с которым коммент //001

П.С. Не согласен с вами в том что, операция  "Где Остаток>0" медленнее по скорости чем внутреннее соединение.
сам неоднократно сталкивался с тем что
Левое соединение + условие Где  отрабатывало быстрее, чем Внутреннее соединение
если помогло нажмите: Спасибо!

vitasw

Менять текст запроса перед компоновкой можно конечно, как самый крайний вариант. Я все еще надеюсь на какой-то другой волшебный способ.
А по скорости... - ну прям не знаю, в принципе я и раньше пару раз слышал подобные утверждения, но в своей практике сколько я не тестировал подтвердить это мне не удалось. Получалось или сопоставимые цифры или "Где" работает хуже.

k_aleks80

Замени вложенный запрос на временную таблицу - производительность выше, проверено:
ВЫБРАТЬ
    Номенклатура.Ссылка КАК Номенклатура
Поместить ВТ
ИЗ
    Справочник.Номенклатура КАК Номенклатура
ГДЕ
    Номенклатура.ЭтоГруппа = ЛОЖЬ
;

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

УНИЧТОЖИТЬ ВТ

vitasw

А вот знаешь, я сам ярый сторонник того, что ВТ работает быстрее, чем вложенный запрос. А вот на этом отчете моя вера пошатнулась. Потратил 2 дня на переписание запроса с вложенных запросов на временные таблицы, а результат 0,1 (ноль целых одна десятая) в том смысле, что прирост по скорости составил не более 0.8 секунды. На вложенном запросе отчет строится за 17,8сек, а на временных таблицах - около 17сек. В общем оптимизма мне этот факт явно поубавил.

LexaK

проверьте все места где в условиях есть ИЛИ
по возможности исключите их
сам сталкивался с этим,
еще
выполните запрос в консоли, проверьте все временные таблицы из размеры, может где-то мультипликация и количество строк многие миллионы.
если помогло нажмите: Спасибо!

k_aleks80

Если тебе надо тупо заменить "ЛЕВОЕ" на "ВНУТРЕННЕЕ", в зависимости от параметра, попробуй так:
Запрос.Текст = "ВЫБРАТЬ
               |    ВложенныйЗапрос.Номенклатура,
               |    ТоварыНаСкладахОстатки.КоличествоОстаток
               |ИЗ
               |    (ВЫБРАТЬ
               |        Номенклатура.Ссылка КАК Номенклатура
               |    ИЗ
               |        Справочник.Номенклатура КАК Номенклатура
               |    ГДЕ
               |        Номенклатура.ЭтоГруппа = ЛОЖЬ) КАК ВложенныйЗапрос
               |        &ВИД_СОЕДИНЕНИЯ РегистрНакопления.ТоварыНаСкладах.Остатки КАК ТоварыНаСкладахОстатки
               |        ПО ВложенныйЗапрос.Номенклатура = ТоварыНаСкладахОстатки.Номенклатура";

Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ВИД_СОЕДИНЕНИЯ", ВидСоединения());

Функция ВидСоединения()
    Если <Условие1> Тогда
        Возврат "ВНУТРЕННЕЕ СОДИНЕНИЕ";
    КонецЕсли;

    Если <Условие2> Тогда
        Возврат "ЛЕВОЕ СОЕДИНЕНИЕ";
    КонецЕсли;
КонецФункции

P.S. Правда, при таком подходе теряется гибкость запроса, т.е. в конструктор запроса ты уже не зайдешь ...

vitasw

Цитата: LexaK от 19 мар 2015, 14:06выполните запрос в консоли, проверьте все временные таблицы из размеры, может где-то мультипликация и количество строк многие миллионы.
Да нет, криминала там такого нету. Там есть другой глобальный тупой криминал, но насколько я понимаю - это было условие заказчика. Есть 2 вложенные схемы СКД. В каждой из них запрос на 600-800 строк. Эти 2 схема отличаются только одним элементарным условием типа "Где Ссылка в (&Список)" и "Где Не Ссылка в (&Список)". Все прочее идентично. Т.е. 2 раза выполняется один и тот же очень большой запрос. А все это нужно только для того, чтобы каждая из вложенных схем выводилась со своим заголовком таблицы типа
"Акционный товар"
"Шапка таблицы отчета"
" перечень товара"
"3 строки пробелов"
"Не акционный товар"
"Шапка таблицы отчета"
" перечень товара"

При виде такого изврата весь мой фэншуй очень пошатнулся. И что самое непонятное никаких фич, присущих СКД в этом отчете нет. Ни выбора группировок, ни выбора отображаемых полей, ни произвольных отборов - НИЧЕГО. На форму выведены произвольные реквизиты и затем программная установка отборов на основании реквизитов на форме. + В отчет выводятся картинки. Понять идею выбора СКД в таких условиях я не в силах.
При этом я не могу сказать, что отчет писал совсем уж второклассник. Такое ощущение, что писал отчет достаточно неплохой программист, но с дулом у виска.
Добавлено: 19 мар 2015, 14:43


Цитата: k_aleks80 от 19 мар 2015, 14:26Если тебе надо тупо заменить "ЛЕВОЕ" на "ВНУТРЕННЕЕ", в зависимости от параметра, попробуй так
Как изменить текст запроса - это я в курсе. Уже писал, что этот вариант остается на крайний случай. Особый цинус вопроса в том, чтобы так составить запроса/настройки СКД, чтобы имея неизменный текст запроса в зависимости от параметра менялось "Левое" на "Внутренее"
Что-то типа
Выбор Когда &Параметр Тогда ЛевоеСоединение РегисрОстатки...
Иначе ВнутренееСоединение РегистрОстатки... Конец.
Я понимаю, что формирую задание как обычный "заказчик": "Хочу чтоб все было хорошо".


Теги:

Похожие темы (5)

Рейтинг@Mail.ru

Поиск