Вход | Регистрация
 

Как избежать рваного запроса

Как избежать рваного запроса
Я
   golem14
 
20.07.21 - 06:24
Мне нужно добавить в запрос условие которое может быть включено иди выключено.

Где Документ.Валюта = &Рубли

Я сделал через динамическое построение текста запроса:

+ ДопУсловие +

ну и установка параметра

Запрос.УстановитьПараметр("Рубли", Справочники.Валюты.НайтиПоНаименованию("RUB"));

Но я не хочу чтобы запрос собирался из кусочков, это неудобно для дальнейшей разработки и отладки.
Как можно сделать это динамическое условие более удобным и понятным?
   dubolom
 
1 - 20.07.21 - 06:29
Если СКД, то фигурные скобки.
Если нет, то
ГДЕ &ЕстьВалюта = ЛОЖЬ ИЛИ Документ.Валюта = &Рубли
И передаёте дополнительный параметр, включающий/выключающий условие.
   ILM
 
Модератор
2 - 20.07.21 - 06:32
ВЫБОР - вот ваш выбор! 

Например условие в секции запроса "ГДЕ":

ГДЕ
    ВЫБОР 
         КОГДА &Рубли = НЕОПРЕДЕЛЕНО
           ТОГДА ИСТИНА 
     ИНАЧЕ Документ.Валюта =&Рубли 
    КОНЕЦ
   spectre1978
 
3 - 20.07.21 - 06:33
Внутри запроса допустим комментарий//.

Можно в тексте сделать закомментированное условие, а в случае необходимости выпонить СтрЗаменить (ТекстЗапроса, //', ''). Добавив после // некое ключевое слово, это можно без проблем расширить на множество условий.
   Адинэснег
 
4 - 20.07.21 - 06:39
(0) Схема запроса
Привет из 2018
   ILM
 
Модератор
5 - 20.07.21 - 06:39
(3) Это не удобно, давно в 2006 году это было нормой в УПП. Потом сделали отдельные запросы, так как при работе с конструктором запросов все комментарии удаляются.
   Адинэснег
 
6 - 20.07.21 - 06:41
СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(Запрос.Текст);
// ковыряем запрос как объект

Запрос.Текст = СхемаЗапроса.ПолучитьТекстЗапроса();
   Адинэснег
 
7 - 20.07.21 - 06:45
если принципиально через запрос, то передавай параметр "... ГДЕ &НужноВключитьОтбор И Документ.Валюта = &Рубли"
Запрос.УстановитьПараметр("НужноВключитьОтбор ", ОтборВключаем);
   golem14
 
8 - 20.07.21 - 06:49
сделал так:
&ТолькоРублевыеПлатежи = Ложь ИЛИ ЗнРДС.Валюта = &Рубли
   golem14
 
9 - 20.07.21 - 06:49
(6) а что за схема запроса? чем это отличается от того что я просто буду править текст запроса как строку?
   ДенисЧ
 
10 - 20.07.21 - 06:51
(9) Это будет стильно и модно.
   golem14
 
11 - 20.07.21 - 06:55
(10) и чем оно тогда отличается от построения через СКД?
   Адинэснег
 
12 - 20.07.21 - 07:06
(9) когда запрос нужно будет изменить не в 2х, а 22х местах
(11) СКД то тут причем? 🤣
   ДедМорроз
 
13 - 20.07.21 - 07:08
А теперь представьте,что у вас таких условий несколько.
Поэтому,или использовать СКД с автовключением условий или строить текст запроса из частей - например - все условия,которые применяются в массив,а потом СтрСоединить.
   Документовед
 
14 - 20.07.21 - 07:08
Запрос.УстановитьПараметр("спСтатейЗатратИсключений", Отчет.спСтатейЗатратИсключений);
Запрос.УстановитьПараметр("ЕстьспСтатейЗатратИсключений", Отчет.спСтатейЗатратИсключений.Количество()>0);


Запрос.УстановитьПараметр("Организация", Отчет.Организация);
Запрос.УстановитьПараметр("ЕстьОрганизация", ЗначениеЗаполнено(Отчет.Организация));



                  |                ВЫБОР
                  |                    КОГДА &ЕстьОрганизация
                  |                        ТОГДА Организация = &Организация
                  |                    ИНАЧЕ ИСТИНА
                  |                КОНЕЦ,

                  |                    И ВЫБОР
                  |                        КОГДА &ЕстьспСтатейЗатратИсключений
                  |                            ТОГДА НЕ Субконто2 В ИЕРАРХИИ (&спСтатейЗатратИсключений)
                  |                        ИНАЧЕ ИСТИНА
                  |                    КОНЕЦ,
   Документовед
 
15 - 20.07.21 - 07:09
+ можно проще:  Организация = &Организация или не &ЕстьОрганизация

Но так хуже читается
   Адинэснег
 
16 - 20.07.21 - 07:11
(14)(15) главное -  вовремя
   Малыш Джон
 
17 - 20.07.21 - 07:15
(0) Или, как выше советуют, делать составное условие,

Или в тексте запроса поставить "ГДЕ &МоеУсловие", а потом в коде ТекстЗапроса = СтрЗаменить(ТекстЗапроса,"&МоеУсловие", "...то условие которое нужно...")

Плюс второго способа, что условие запроса получается проще и в конструкторе такой текст запроса тоже открывается.
   golem14
 
18 - 20.07.21 - 07:36
(6) Запрос как объект это таки интересно, буду пробовать, а говорят ещё что язык 1С не объектный :-)
В типовой ERP вижу много мест где это используется, но похоже кроме писателей типовых это никому не сдалось и только запутывает.
   golem14
 
19 - 20.07.21 - 07:44
схема запроса это просто
https://infostart.ru/upload/iblock/89a/shema_m.jpg
   TormozIT
 
20 - 20.07.21 - 08:32
Олды в доме. Они приносят древнюю магию.
Построитель запроса для таких целей оптимален.

Допустим есть запрос

выбрать т.Регистратор из РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто как т
ГДЕ 12 <> т.ВидСубконтоДт2 

И надо условно добавить условие 
т.Сумма > 100

Делай
выбрать т.Регистратор из РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто как т
ГДЕ 12 <> т.ВидСубконтоДт2 
{ГДЕ 
    (т.Сумма > 100) КАК ТолькоБольшиеСуммы
}

Дальше в настройках построителя условно добавляешь отбор по полю ТолькоБольшиеСуммы

построитель = Новый ПостроительЗапроса;
построитель.Текст = 
"выбрать т.Регистратор из РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто как т
|ГДЕ 12 <> т.ВидСубконтоДт2 
|{ГДЕ 
|    (т.Сумма > 100) КАК ТолькоБольшиеСуммы
|}";
построитель.ЗаполнитьНастройки();
Если 1=1 Тогда
    построитель.Отбор.Добавить("ТолькоБольшиеСуммы").Установить(Истина);
КонецЕсли;
Запрос = построитель.ПолучитьЗапрос();

и при добавленном элементе отбора получаешь запрос 

ВЫБРАТЬ
    т.Регистратор КАК Регистратор
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто КАК т
ГДЕ
    12 <> т.ВидСубконтоДт2
    И т.Сумма > 100 = &Параметр1
https://i.imgur.com/pG91Urp.png

а без добавленного элемента отбора получаешь запрос

ВЫБРАТЬ
    т.Регистратор КАК Регистратор
ИЗ
    РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто КАК т
ГДЕ
    12 <> т.ВидСубконтоДт2
https://i.imgur.com/DlnlR6M.png
   TormozIT
 
21 - 20.07.21 - 08:41
(20) Компоновка отработает по той же схеме и более современна, но потребует больше писать кода.
   TormozIT
 
22 - 20.07.21 - 08:44
(20) Такой подход правда годится только для условий в верхней группе "И".
   TormozIT
 
23 - 20.07.21 - 09:08
А самым универсальным подходом конечно является СтрЗаменить(). Вставляем в запрос нейтральный уникальный фрагмент в группу условий и к нему привязываем условные вставки динамических фрагментов
Например для группы "И" можно применять фрагмент - {И "ТочкаВставкиИ1" = "ТочкаВставкиИ1"}, а для группы "ИЛИ" - {ИЛИ "ТочкаВставкиИ1" = 0}.
При этом для повышения надежности вставки контролируем наличие опорного фрагмента.

Текст = "выбрать т.Регистратор из РегистрБухгалтерии.Хозрасчетный.ДвиженияССубконто как т
|ГДЕ 12 <> т.ВидСубконтоДт2 Или ""ТочкаВставкиИЛИ1"" = 0 ИЛИ (11 <> т.ВидСубконтоДт2 И ""ТочкаВставкиИ1"" = ""ТочкаВставкиИ1"")";
Текст = ирОбщий.СтрЗаменитьЛкс(Текст, """ТочкаВставкиИЛИ1"" = 0", " ИЛИ Т.Сумма > 100", Истина);
Текст = ирОбщий.СтрЗаменитьЛкс(Текст, """ТочкаВставкиИ1"" = ""ТочкаВставкиИ1""", " И Т.Сумма > 200", Истина);

Функция СтрЗаменитьЛкс(Знач ГдеЗаменять, Знач ЧтоЗаменять, Знач НаЧтоЗаменять, ОставитьЧтоЗаменять = Ложь, ВыброситьИсключениеПриОтсутствии = Истина) Экспорт 
    
    Если ВыброситьИсключениеПриОтсутствии И Найти(ГдеЗаменять, ЧтоЗаменять) < 1 Тогда
        ВызватьИсключение "Шаблонная строка """ + ЧтоЗаменять + """ не найдена в тексте";
    КонецЕсли; 
    Если ОставитьЧтоЗаменять Тогда
        НаЧтоЗаменять = ЧтоЗаменять + НаЧтоЗаменять;
    КонецЕсли; 
    Результат = СтрЗаменить(ГдеЗаменять, ЧтоЗаменять, НаЧтоЗаменять);
    Возврат Результат;

КонецФункции
   TormozIT
 
24 - 20.07.21 - 09:09
(23) Ошибся. Надо
для группы "ИЛИ" - {ИЛИ "ТочкаВставкиИЛИ1" = 0}
   Документовед
 
25 - 20.07.21 - 09:28
(23)

Почему вместо "{ИЛИ "ТочкаВставкиИ1" = 0}" 

не вставить: "ИЛИ &ТочкаВставкиИ1"

А потом уже  Текст = ирОбщий.СтрЗаменитьЛкс(Текст, "&ТочкаВставкиИ1", " ИЛИ Т.Сумма > 100", Истина);

Не так вырвиглазно выглядит.
   TormozIT
 
26 - 20.07.21 - 09:31
(25) Тогда придется в запросе еще устанавливать служебные параметры "ТочкаВставки*" с правильными значениями Истина/Ложь. Дело вкуса.
   Галахад
 
27 - 20.07.21 - 09:34
(23) А что за постфик "Лкс"?
   TormozIT
 
28 - 20.07.21 - 09:35
(27) "Лучший Код Старыха"
   Галахад
 
29 - 20.07.21 - 09:39
(28) :-)
   Cyberhawk
 
30 - 20.07.21 - 09:50
(26) В варианте из (25) в запросе не остается служебных параметров, поэтому их устанавливать не требуется
 
 
   1CnikPetya
 
31 - 20.07.21 - 09:50
Мне нравится такой вариант, его и применяю:

Запрос.Текст = "ВЫБРАТЬ
...
ИЗ
Таблица
ГДЕ
 &УсловиеНаВлюту";

Потом уже постобработка по тексту:

Если НуженОтборПоВалюте Тогда
 СтрЗаменить(ТекстЗапроса, "&УсловиеНаВлюту", "Таблилца.Валюта = &Рубль");
 Запрос.УстановитьЗначениеПараметра("Рубль", Рубль);
Иначе
 СтрЗаменить(ТекстЗапроса, "&УсловиеНаВлюту", "ИСТИНА");
КонецЕсли;

В итоге запрос открывается конструктором, хорошо читаем, не передаются лишние параметры и не пишутся лишние условия.
   TormozIT
 
32 - 20.07.21 - 09:57
(30) Не понял тебя. Замена же выполняется условно, т.е. может не применяться.
   ManyakRus
 
33 - 20.07.21 - 09:58
(31) Текст запроса должен быть такой чтоб его легко можно было скопировать в консоль запросов.
Такой код ужасный для консоли отчётов.
Надо писать комментарии в запросе а потом заменять комментарий на текст (и не пользоваться конструктором никогда)
   TormozIT
 
34 - 20.07.21 - 10:00
(33) Условие можно быть полностью динамическое, т.е. заранее не известна строка, на которую заменять будем.
   TormozIT
 
35 - 20.07.21 - 10:01
(33) Ну и запрет использования конструктора - сразу минус 5 к универсальности.
   arsik
 
36 - 20.07.21 - 10:02
(31) Так же делаю.
   1CnikPetya
 
37 - 20.07.21 - 10:05
(33) Конструктором пользуюсь, чтобы накидать основу запроса и проверить его синтаксис. Мне не нравится форматирование конструктора, но понимаю тех, кто им пользуется. Так же удобно смотреть структуру запросов на несколько экранов.

По подстановке параметров (34) правильно сказал. А в моем варианте можно этот параметр поставить ИСТИНА и будет в консоли вариант без его учета. А дальше уже крути от потребностей.
   TormozIT
 
38 - 20.07.21 - 10:05
(31) Опасность тут в том, что потом можно дописать к этому условию " ИЛИ Сумма = 0" и тогда работать итоговое условие будет не так, как ожидалось. Поэтому надо в имени точки привязки лучше обозначать ее тип (Истина/Ложь/И/Или).
   1CnikPetya
 
39 - 20.07.21 - 10:16
(38) Имеешь ввиду

"ГДЕ
 &УсловиеНаВлюту
 ИЛИ Сумма = 0"

или

СтрЗаменить(ТекстЗапроса, "&УсловиеНаВлюту", "Таблилца.Валюта = &Рубль ИЛИ Сумма = 0")?

Немного не понимаю, в чем риск.
   TormozIT
 
40 - 20.07.21 - 10:20
(39) Текст = "... ГДЕ &УсловиеНаВлюту ИЛИ Сумма = 0"
СтрЗаменить(ТекстЗапроса, "&УсловиеНаВлюту", "ИСТИНА");
   1CnikPetya
 
41 - 20.07.21 - 10:28
(40) Ну, вот тут я не согласен. Просто по тексту запроса получается вполне явно: условие на валюту проверяем при ненулевой сумме документа. А какое условие на валюту - это уже отдельный вопрос.
   DeeK
 
42 - 20.07.21 - 12:07
если запрос простой и нужно маленький кусочек в нем динамически вставить то проблем с отладкой не будет, а когда по 30 временных таблиц, то юзаю менеджер, там все тоже можно удобно посмотреть
   SiAl-chel
 
43 - 20.07.21 - 14:44
(2) Лучше через ИЛИ, читается легче.
&Рубли = НЕОПРЕДЕЛЕНО ИЛИ Документ.Валюта = &Рубли
   Документовед
 
44 - 20.07.21 - 16:02
(43) откуда там «неопределено»  там будет пустая ссылка на справочник.
   Документовед
 
45 - 20.07.21 - 16:03
(43) читается проще через условие
   Вафель
 
46 - 20.07.21 - 16:07
Пиши не + ДоУсловие +, а &ДопУсловие
А остальное все так же
   OldCondom
 
47 - 20.07.21 - 16:15
(46) + 100. Также использую &ТекстФильтра.
   Кирпич
 
48 - 20.07.21 - 16:15
Так пишу
ТекстЗапроса = "ВЫБРАТЬ %1 ИЗ Справочник.Номенклатура ГДЕ %2";

Поля = "Наименование, Код";
Условие = "Код = 123";

Запрос.Текст = СтрШаблон(ТекстЗапроса, Поля, Условие);

   АнализДанных
 
49 - 21.07.21 - 10:14
(0) (20) Мне в таких ситуациях тоже нравится использовать построитель запроса. В этом случае можно использовать конструктор запросов, код более понятный становится. Ниже пример процедуры, которая сама формирует текст запроса.

ТекстЗапроса = "ВЫБРАТЬ
               |    Номенклатура.Ссылка КАК Ссылка
               |ИЗ
               |    Справочник.Номенклатура КАК Номенклатура
               |ГДЕ
               |    Номенклатура.Ссылка <> &ИсключаемаяНоменклатура
               |{ГДЕ
               |    Номенклатура.СтавкаНДС.* КАК СтавкаНДС,
               |    Номенклатура.Производитель.*,
               |    Номенклатура.Наименование}";

ДинамическиеОтборы = Новый Структура;

Если ИспользоватьОтбор_СтавкаНДС Тогда
        
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("ВидСравнения", ВидСравнения.ВСписке);
    ПараметрыОтбора.Вставить("Значение",      СписокСтавокНДС);
    
    ДинамическиеОтборы.Вставить("СтавкаНДС", ПараметрыОтбора);    

КонецЕсли;

Если ИспользоватьОтбор_Производитель Тогда
    ДинамическиеОтборы.Вставить("Производитель", Производитель);
КонецЕсли;

Если ИспользоватьОтбор_Наименование Тогда
    
    ПараметрыОтбора = Новый Структура;
    ПараметрыОтбора.Вставить("ВидСравнения", ВидСравнения.НеСодержит);
    ПараметрыОтбора.Вставить("Значение",      "Поддон");

    ДинамическиеОтборы.Вставить("Наименование", ПараметрыОтбора);
    
КонецЕсли;

ФиксированныеПараметры = Новый Структура;
ФиксированныеПараметры.Вставить("ИсключаемаяНоменклатура", ИсключаемаяНоменклатура);

Запрос = СформироватьЗапросПоДинамическимУсловиям(ТекстЗапроса, ДинамическиеОтборы, ФиксированныеПараметры);




// Создает объект "запрос", используя расширение языка запроса

//
// Параметры:

//  ТекстЗапроса             - Строка         - Текст запроса, в котором может содержаться расширение языка запроса
//  ДинамическиеПараметры    - Структура     - Значение необязательных параметров запроса, где:

//    * Ключ     - Строка - Имя параметра из расширения языка запросов
//    * Значение - произвольное значение параметра или Структура, где:

//      * ВидСравнения - ВидСравнения - содержит вид сравнения
//      * Значение     - произвольное значение параметра

//  ФиксированныеПараметры - Структура      - Значение обязательных параметров запроса, где:
//    * Ключ     - Строка - Содержит имя параметра запроса

//    * Значение - Произвольное - Значение параметра
// 

// Возвращаемое значение:
//   Запрос - Объект "Запрос" - Запрос с установленными параметрами и текстом запроса.

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


Список тем форума
 
ВНИМАНИЕ! Если вы потеряли окно ввода сообщения, нажмите Ctrl-F5 или Ctrl-R или кнопку "Обновить" в браузере.