gifts2017

Условные условия и запросы

Опубликовал Александр Лапшин (zfilin) в раздел Программирование - Практика программирования

При составлении запросов часто бывает так, что нужно вставить условие отбора в запрос в зависимости от того, пустое значение отбора или оно заполнено. А конструктор запросов перестает работать из-за включений в код запроса.

Например, нужно получить список всех товаров по складу, но если в качестве склада передано пустое значение, то необходимо получить список товаров по всем складам (т.е. склад не выбран).

Как правило в таких случаях модифицируют текст запроса "на лету" примерно таким образом:


Запрос.Текст =
"ВЫБРАТЬ
|   Учет.Товар,
|   Учет.Количество
|ИЗ
|   Документ.Учет КАК Учет
|" + ?(ЗначениеЗаполнено(Склад),"ГДЕ Учет.Склад = &Склад","");

Без сомнений, такой способ имеет достоинства, но у него есть и существенный недостаток. При таком "ручном" вмешательстве в текст запроса, перестает работать очень удобный инструмент - конструктор запросов. Он просто не понимает наших "посторонних" включений. Особенно ярко это проявляется когда речь идет о "монструозных" запросах на несколько страниц. Сталкиваясь с таким великаном и обнаруживая в нем включения кода 1С, я всегда думаю такие плохие вещи, что будет неловко их тут повторять.

Однако, единственный ли это способ достичь желаемого, сделать так, чтобы склад не учитывался в отборе, если он не заполнен? Не единственный! Если немного пораскинуть мозгами очень просто перенести условную конструкцию внутрь самого запроса, например вот так:

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

Никакого волшебства, всего-лишь банальное использование оператора "ИЛИ". Если склад не заполнен то и все выражение всегда будет истинным, а значит в выборку попадут все склады.

Конечно, такой способ несколько усложняет само условие запроса, но мне кажется, что это стоит того, чтобы получить преимущества предоставляемые конструктором.

Что же с производительностью? Действительно, производительность в таком случае немного падает. Я сделал небольшую конфигурацию, чтобы сделать замеры. Желающие могут скачать ее и попробовать померить производительность самостоятельно (1C 8.2.10.77).

Исходные данные: 20 документов, 7 товаров, 3 склада, ~10000 вызовов запроса (5000 с пустым и 5000 с заполненным складом).

Запрос в котором условие подставляется в текст средствами языка 1С:

SpeedMod

Как видите, 10002 запроса (строка 15) выполняется за 8,2 секунды.

А вот, результаты выполнения запроса с внесенным внутрь условием:

SpeedCond

Результат (59-я строка) выполнения - 11,4 секунды. То-есть 3,2 секунды на ~10000 запросов.

Можно было бы провести замеры с вложенными запросами и соединениями или с другими объемами данных, но в целом понятно что для простых случаев потеря производительности несущественная. К тому же запросы-монстры не часто вызываются по 10000 раз за один раз.

Товарищи мне подсказывают, что данные в таком случае берутся из кэша, поэтому производительность оценивается не совсем верно. Я предполагаю сделать еще замеров в будущем на разные способы и объемы данных или сделайте это сами.

 

Какой из способов использовать, конечно, решать вам.

А я хочу пожелать вам хорошего дня и хорошего кода.

Спасибо за внимание.

 

P.S.: Статья получила множество отзывов и уважаемое сообщество насоветовало еще кучу способов борьбы с условиями.

 

Уважаемый alexk-is советует использовать построитель отчета:

ПостроительОтчета.Текст =
"ВЫБРАТЬ
|   Учет.Товар,
|   Учет.Количество
|ИЗ
|   Документ.Учет КАК Учет
|{ГДЕ
|   Учет.Склад.*}"
;
ПостроительОтчета.ПолучитьЗапрос().Выполнить();

Yashazz ставит комментарии, выполняет поиск и замену в тексте запроса перед выполнением, но сокрушается, что конструктор режет комментарии:

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

Зато Alias прекрасно развивает идею и советует делать так:

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

Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеСклада",?(ЗначениеЗаполнено(ВыбСклад),"Учет.Склад = &Склад","Истина"));

Без сомнения в способе куча плюсов - и конструктор не режет ничего и запрос читается нормально и тормозов нет.

4ishиспользует выбор:

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

Тоже хороший способ.

А Vit aka proger изящно применяет "в иерархии":

Запрос.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|ГДЕ
| Учет.Склад в иерархии( &Склад))"
;

Serj1С иногда использует:

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

 

Всем спасибо за замечательные подсказки, я обязательно возьму кое-что себе на вооружение.

Ну, и, конечно обсуждение еще продолжается.

 

Оригинал в блоге автора

Скачать файлы

Наименование Файл Версия Размер Кол. Скачив.
УсловияИЗапросы
.zip 22,93Kb
19.10.10
132
.zip 22,93Kb 132 Скачать

См. также

Подписаться Добавить вознаграждение

Комментарии

1. Алексей Константинов (alexk-is) 19.10.10 05:27
Может так?

ПостроительОтчета.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|{ГДЕ
| Учет.Склад.*}"
;
ПостроительОтчета.ПолучитьЗапрос()).Выполнить();


Посмотреть как это работает, ну, и другие варианты оптимизации запросов можно здесь http://www.infostart.ru/public/69707/

И еще "Учет.Склад.Ссылка = " плохое условие, правильнее будет "Учет.Склад = "
RTFM; hulio; Evg-Lylyk; Ish_2; Serj1C; +5 Ответить 5
2. Serj (Serj1C) 19.10.10 07:31
(1) +1 за использование построителя

(0) Прошлый век. На СКД также предлагаете мучаться?
3. Владимир Ленгин (vlengin) 19.10.10 09:24
Что значит "моструозных", может имелось ввиду "монстроозных"?
4. Владимир Ленгин (vlengin) 19.10.10 09:31
5. Александр Лапшин (zfilin) 19.10.10 10:09
(4) Ага. Точно!

(1) Насчет "Учет.Склад.Ссылка = " согласен, это я "очепятался". И спасибо, что предложили еще более совершенный способ достигнуть требуемого результата. Правда, я не совсем понял при чем тут ваш замечательны журнал, но видимо какая-то связь есть...
6. Яков Коган (Yashazz) 19.10.10 10:13
Я в таких случаях пишу комментарии в тексте запроса.
Например
|ГДЕ
|Склад = &УсловныйСклад
|//УсловиеНаТовар//";
и потом просто СтрЗаменить(ТекстЗапроса,"//УсловиеНаТовар//","И Товар = &УсловныйТовар")

Конечно, конструктор режет комментарии, но хоть прочитать запрос при этом может.
7. Alex (4ish) 19.10.10 10:41
Еще как вариант:

|ГДЕ
|ВЫБОР
|КОГДА &Склад <> ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
|ТОГДА ПоступлениеТоваровУслугТовары.Ссылка.Склад = &Склад
|ИНАЧЕ ИСТИНА
|КОНЕЦ
8. Александр Лапшин (zfilin) 19.10.10 10:55
(7) Точно! =)

(6) Да, жаль что режет, так тоже способ ничего.

(1) А! Спасибо, уже оценил!
9. Алексей Константинов (alexk-is) 19.10.10 11:05
(8) По ссылке в (1) используется много разных запросов. Мой любимый по структуре подчиненности документов.
10. Александр Лапшин (zfilin) 19.10.10 11:11
(9) Ага, вот смотрю как раз. Круто, че сказать.
11. Артур Аюханов (artbear) 19.10.10 13:39
По опыту скажу:
1. Построитель не всегда удобен :(
2. использование как (0), так и (7) не всегда удобно.
Лично я чаще юзаю сравнение не с ПустаяСсылка, а с NULL.
12. Артур Аюханов (artbear) 19.10.10 13:49
(0) ОФФ Увидел в твоем блоге заметки про тестирование.
По опыту скажу: Сценарное тестирование долго, неудобно, негибко :(
Посмотри
Юниттестирование на восьмерке (готовый набор для тестирования, у меня постоянно в работе) http://www.1cpp.ru/forum/YaBB.pl?num=1267016427/94#94
Тестирование разработок на платформе 1С. Управление данными http://www.1cpp.ru/forum/YaBB.pl?num=1273213867/35#35 (это схемы работы с тестовыми данными и обсуждение разных схем)
.
Также можешь посмотреть мою разработку
Повышение удобства разработки в среде 1С http://infostart.ru/public/65526/
есть спец.раздел Тестирование
13. Александр Лапшин (zfilin) 19.10.10 14:04
(12) О! Спасибо, тестирование меня очень интересует, обязательно посмотрю.
14. Виталий Криволапов (Vit aka proger) 19.10.10 16:34
а я обычно пишу так:
Запрос.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|ГДЕ
| Учет.Склад в иерархии( &Склад))";
Если склад пустой, выбирается по всем имеющимся складам



Хотя я обычно делаю запрос по регистрам
|ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки(&КонПериода, Склад в иерархии(&Склад))

happy_saint; zfilin; gaglo; +3 Ответить 1
15. Александр Полетаев (Alias) 19.10.10 17:27
(6) А я пишу так. Конструктор отрабатывает без проблем, ничего не теряется... и сама строка "&УсловиеСклада" выглядит понятнее чем какие-то сложные условия. И выполнение запроса (это важно!) при этом не тормозит. И конструктор ничего не режет. Короче, сплошные плюсы :)

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

Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеСклада",?(ЗначениеЗаполнено(ВыбСклад),"Учет.Склад.Ссылка = &Склад",""));
Innuil; zfilin; gaglo; tango; valm0unt; +5 Ответить 2
16. Андрей Пастухов (Minotavrik) 20.10.10 10:51
Есть хороший способ отлаживать большие и страшные, текст которых изменен в конфигураторе различными операторами.

Я делаю так:

Нахожу строчку Запрос.выполнить(). Ставлю точку останова и перехожу в отладку. Когда точка срабатывает, делаю следующее:
Нажимаю на кнопку "Вычислить выражение";
в поле пишу Запрос.Текст (если через построитель то ПостроительОтчета.ПолучитьЗапрос().Текст);
Копирую текст запроса и отлаживаю его в консоли.
sanfoto; NazarovV; МимохожийОднако; dandrontiy; +4 Ответить 3
17. Александр Лапшин (zfilin) 20.10.10 14:13
О! Спасибо всем, сколько способов!
Нужно обязательно будет включить их в текст самой статьи.
18. Борис Скворцов (gaglo) 20.10.10 14:16
(15) Тут не понял: если "&УсловиеСклада" заменить на "", то получится запрос
"ВЫБРАТЬ
...
|ГДЕ ";
- но ведь он синтаксически неверен?

Я пишу почти так же, только вместо "ГДЕ &УсловиеСклада" ставлю "ГДЕ Истина".
Выглядит не так уж понятно, и наводит на не те мысли (сравни с "Где справедливость?")
Зато можно выполнять и без всяких СтрЗаменить...
19. Александр Лапшин (zfilin) 20.10.10 14:32
(16) Спасибо за подсказку, я тоже использую такой способ для отладки. =)
20. Maxim (mst) 20.10.10 14:55
а я в 7ке пишу не "=" а "в" и работает независимо выбран элемент или нет... никогда не писал =, потому что при "в" в запрос попадают еще и элементы из подгрупп выбранной группы справочника.
21. Игорь <...> (I_G_O_R) 20.10.10 22:44
(16) Вы наверное большие запросы не видели, в ЗУПе они почему-то не помещаются :cry:
22. Артур Аюханов (artbear) 21.10.10 07:13
(21) Все помещается, нужно только включить выражение с текстом в табло просмотра, далее щелкнуть на тексте, и нажать лупу. откроется окошко для просмотра текста, откуда и можно скопировать текст.

(16) (19) Копирование текста запроса вручную неудобно, т.к. параметры придется самому ставить :(
лучше пользоваться спец.консолями, которые могут отлаживать сам запрос.
В итоге в отладчике вычисляешь код Отладить(Запрос) и в режиме Предприятия открывается консоль с полным запросом (текст, параметры, временные таблицы и т.д.)
Посмотрите мою разработку http://infostart.ru/public/65526/
В ней я описал различные фичи, в т.ч. и мощнейшие консоли.
23. Александр Полетаев (Alias) 21.10.10 11:54
(18) Ой, конечно, Вы абсолютно правы! Поспешил с написанием комментария. У меня просто обычно этот приём используется как часть сложного условия (то есть, например, условие на Организацию есть всегда). Тогда пустой строки никак не бывает.

В простом же случае можно писать либо "ИСТИНА ИЛИ &УсловиеСклада", либо в СтрЗаменить() включать строку с указанием ГДЕ ("ГДЕ Учет.Склад.Ссылка = &Склад")
А в комментарии смешал оба этих случая. :) спасибо что указали на неточность.

Выбор варианта зависит от удобства в конкретном случае.
24. Алексей Лапицкий (Lapitskiy) 22.10.10 14:16
с выводами по скорости не согласен, если выполнять запросы в цикле, выборка идет из кэша! Надо не запрос в цикле делать, а 1 запрос по большой базе.
25. Александр Лапшин (zfilin) 22.10.10 14:24
(24) Согласен, я для этого и приложил конфу, чтобы можно было по-разному попробовать.
26. rasswet (rasswet) 22.10.10 16:53
в если из ГДЕ Учет.Склад.Ссылка убрать ссылку?
27. Александр Лапшин (zfilin) 22.10.10 18:30
(26) Про ссылку еще в самом начале говорили, она там случайно оказалась.
Наверное, надо подредаткировать...
28. Игорь <...> (I_G_O_R) 22.10.10 22:58
(22) я именно так и смотрю, просто в ЗУПе есть такие большие запросы что в этом окне только часть текста (например текст запроса расчета НДФЛ, в нем около 5000 строк, а помещается где-то 3000 с лишним).
29. Яков Коган (Yashazz) 25.10.10 15:00
Способ Alias'a опасен тем, что при достаточно сложной логике условия есть риск запутаться и налажать. Простыми "истина" и "ложь" тоже можно напутать - поставить, например, "Истина" в условие "И", а потом поменять где-то что-то на "Или", условие-то большое, и получить ошибку.
30. Serj (Serj1C) 26.10.10 09:08
(14) "в иерархии" работает медленно!

мне больше нравится (1) и (15)
31. Александр Полетаев (Alias) 26.10.10 09:24
(29) Не согласен. Разбивание большого и сложного условия на несколько маленьких наоборот, упростит понимание условия! Сравните, например, один из предложенных вариантов:

|ВЫБОР
| КОГДА &Склад <> ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка)
| ТОГДА Учет.Склад = &Склад
| ИНАЧЕ ИСТИНА
|КОНЕЦ И
|ВЫБОР
| КОГДА &Организация <> ЗНАЧЕНИЕ(Справочник.Организации.ПустаяСсылка)
| ТОГДА Учет.Организация = &Организация
| ИНАЧЕ ИСТИНА
|КОНЕЦ

и то что предлагаю я:

|&СкладПодходит И &ОрганизацияПодходит

Что из этого проще? :)
Ваш довод работает против Вас -- так как в сложном условии как раз-таки проще запутаться, чем в условии, разбитом на простые блоки.
32. Serj (Serj1C) 27.10.10 09:39
Вместо (31) я использую иногда:

|ГДЕ
| &Склад В (Выборка.Склад, ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка))
33. Роман Романов (romansun) 21.02.11 15:05
(0) добавлю свои пять копеек. Похоже на уже описанные тут варианты..

довольно стандартная реализация чекбокса в запросе:

|ГДЕ (&флПДК = ложь ИЛИ (&флПДК = истина И ДокументРасчетов.ПризнакДополнительногоКонтроля = истина))


вместо динамических запросов использую часто также СтрЗаменить() через примерно такие конструкции:

|ГДЕ Истина
|//секцияКонтрагент И Контрагент = &Контрагент
|//секцияДоговор И Договор = &Договор
|//секцияДокументРасчетов И ДокументРасчетов = &ДокументРасчетов

Конструктор, конечно, срубит ремарку, но я им практически не пользуюсь. Только при первоначальном написании в консоле запросов, чтоб имена реквизитов он мне все вытащил :).
Новиков; +1 Ответить
34. Max Gr. (max082) 18.10.11 12:57
Мне лично еще нравится следующая конструкция:

|
|Где &ВсеСклады ИЛИ Документ.Склад = &Склад
|
35. Александр Лапшин (zfilin) 19.10.11 21:50
(34) max082, Тоже неплохо, а &ВсеСклады это что?
37. Альтаир (Altair777) 07.08.12 14:31
Имхо, лучше все-таки модифицировать текст запроса по условию в коде.
Кстати, во всех примерах опущена установка параметров для запроса. Вот маленький пример как у меня это все объединено:

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

Если
ФильтрПоСрокам Тогда
Запрос.Параметры.Вставить("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.Параметры.Вставить("КонецПериода", КонецДня(КонецПериода));
Иначе
Запрос.Текст = СтрЗаменить(Запрос.Текст, "И ДоговорыКонтрагентов.Дата МЕЖДУ &НачалоПериода И &КонецПериода", "");
КонецЕсли;
Запрос.Параметры.Вставить("МассивОтобранных", МассивОтобранных);
Запрос.Параметры.Вставить("ВидДоговора", ВидДоговора);
Запрос.Параметры.Вставить("ВидВзаиморасчетов", ВидВзаиморасчетов);
ТаблЗапроса2 = Запрос.Выполнить().Выгрузить();
38. Александр Лапшин (zfilin) 07.08.12 15:15
Да, я тоже пользуюсь модификацией текста запроса.
Но я все же применил бы параметр &УсловиеПоДатеДоговора, который бы в зависимости от ситуации менял бы на строку "ДоговорыКонтрагентов.Дата МЕЖДУ &НачалоПериода И &КонецПериода" или на "Истина".

Так в конструкторе запроса, я увижу что у меня есть какое-то условие, которое в последствии будет определяться в коде модуля. А если просто убирать строчку "И ДоговорыКонтрагентов.Дата МЕЖДУ &НачалоПериода И &КонецПериода", то про то, что она в последствии может исчезнуть во время отладки запроса очень просто забыть. И думать потом - вот у меня же четко стоит отбор по датам. Почему ж оно не отбирает-то?
39. Альтаир (Altair777) 07.08.12 15:31
(38) zfilin, а текст кода нормально виден? У меня что-то нет :)

P.S. Вопрос снят. Разобрался.
40. Алекс Ю (AlexO) 07.08.12 15:35
Непонятны восторги.
Ну да, хорошо, собрал в одном месте варианты проверок (да и то не все), - но не систематизированные, без описания применимости и раскрытия смысла.
Есть масса способов сделать условие в запросе.
Их уже множество тут накидали.
1С наделала столько всего, что оно и не нужно так много. Достаточно было сделать одно - но путное и быстрое.
Можно и ВЫБОР...КОГДА, можно и через параметр &Параметр, можно и заменой текста запроса перед выполнением.
ПостроительОтчета для выполнения запроса используют только тру-1сники.
А все же посыл статьи не раскрыт: без динамического формирования запросов во многих случаях не обойтись никак, ничем это не заменишь, и никаких инструментов в 1С для отладки нет.
42. Альтаир (Altair777) 07.08.12 15:37
(38) zfilin,

> И думать потом - вот у меня же четко стоит отбор по датам. Почему ж оно не отбирает-то?

Если это сделать системой, то думать не придется.
Логика простая - если есть параметр запроса, значит он должен заполняться.
А раз он заполняется, то есть код его заполнения.
И в том же самом месте происходит и модификация текста запроса.

Плюс немного экономии - раз параметр не используется, то зачем его вставлять?

ОФФ: А вообще, при отладке очень сложных запросов, текст которых может модифицироваться несколько раз и в нескольких разных местах, лучше в отладчике отловить окончательный текст прямо на стоке Запрос.Выполнить()
43. Александр Лапшин (zfilin) 07.08.12 17:26
(42) Altair777, Ага. Ну, с этой позиции да, полностью согласен.
Но я-то исходил из того, что код могут смотреть и другие люди, которые могут не знать о такой системе и воспринимать выражение "ДоговорыКонтрагентов.Дата МЕЖДУ &НачалоПериода И &КонецПериода" однозначно - есть такое условие, полагая, что заполнение параметров это... Просто заполнение параметров! =) И там только обычное заполнение дат!
А одиночным параметром мы однозначно заставляем того, кто читает код, проверить что за условие скрывается за параметром. Естественно, к имени параметра тот кто будет писать запрос, должен выставлять требования сходные с требованиям к именованию функций. Имя этого параметра должно отражать суть условия.

Собственно, это на самом деле уже детали, и дело вкуса. Кому-то кажется понятнее одно, кому-то другое. Суть одна - модификация текста запроса.
44. Альтаир (Altair777) 07.08.12 17:49
(43) zfilin,

> Ну, с этой позиции да, полностью согласен.
Спасибо :)

Такой подход дает 2 неоспоримых преимущества - возможность использовать конструктор и ускорение выполнения запроса.

P.S. Видел я и второй подход - по условию добавлять строки в текст запроса. Но это гораздо затратнее.
45. Александр Лапшин (zfilin) 07.08.12 17:59
(44) Altair777, Может я не совсем понятно выразился. Сейчас покажу на вашем коде:

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

Если
ФильтрПоСрокам Тогда
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ФильтрПоСрокам", "ДоговорыКонтрагентов.Дата МЕЖДУ &НачалоПериода И &КонецПериода");
Запрос.Параметры.Вставить("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.Параметры.Вставить("КонецПериода", КонецДня(КонецПериода));
Иначе
Запрос.Текст = СтрЗаменить(Запрос.Текст, "&ФильтрПоСрокам", "Истина");
КонецЕсли;
Запрос.Параметры.Вставить("МассивОтобранных", МассивОтобранных);
Запрос.Параметры.Вставить("ВидДоговора", ВидДоговора);
Запрос.Параметры.Вставить("ВидВзаиморасчетов", ВидВзаиморасчетов);
ТаблЗапроса2 = Запрос.Выполнить().Выгрузить();


Чем же оно гораздо затратнее получается, может, я не заметил чего?.. =(
46. Алекс Ю (AlexO) 07.08.12 18:22
(42) Altair777,
лучше в отладчике отловить окончательный текст ....

оо, выдал все профессиональные тайны ... :(
47. Альтаир (Altair777) 07.08.12 18:29
(45) zfilin,
как-то так :)

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

Если
ФильтрПоСрокам Тогда
Запрос.Текст = Запрос.Текст + "
| И ДоговорыКонтрагентов.Дата МЕЖДУ &НачалоПериода И &КонецПериода"
;
Запрос.Параметры.Вставить("НачалоПериода", НачалоДня(НачалоПериода));
Запрос.Параметры.Вставить("КонецПериода", КонецДня(КонецПериода));
КонецЕсли;

Запрос.Параметры.Вставить("МассивОтобранных", МассивОтобранных);
Запрос.Параметры.Вставить("ВидДоговора", ВидДоговора);
Запрос.Параметры.Вставить("ВидВзаиморасчетов", ВидВзаиморасчетов);
ТаблЗапроса2 = Запрос.Выполнить().Выгрузить();


А если условие стоит в середине текста (вложенные запросы)? Хоть вешайся.
48. Альтаир (Altair777) 07.08.12 18:30
(46) AlexO, да?!!! :)
Я бы мог отредактировать свой коммент чтобы не раскрывать тайну, но... все равно останется в цитате.
49. Альтаир (Altair777) 07.08.12 18:34
(45) zfilin,

понял! А если этот текст перекинуть в консоль запросов, то как его отлаживать?
Два понятных параметра НачалоПериода И КонецПериода заменяется на нечто... совсем не понятное :)
50. Александр Лапшин (zfilin) 07.08.12 18:39
(47) Да, добавлением не очень удобно.
(49) Свои минусы есть. В консоли отлаживать не очень удобно, но как вы справедливо заметили для отладки лучше использовать итоговый текст из строки "Выполнить()". =) Раз уж мы тут все замешаны в выдаче страшных секретов. =)))
51. Алекс Ю (AlexO) 08.08.12 10:13
(50) zfilin,
вся проблема - даже не в получить окончательный текст запроса (хотя он и будет в каждом другом случае - разный), а собрать размазанные параметры, чтобы воспроизвести в консоли именно текущий запрос.
Это проблема проблем :)
Я решаю совсем уж оригинальным способом, здесь не указанным.
(48) Altair777,
я отредактировал цитату, теперь ваша очередь :)
но вдруг уже попала в поисковую базу яндекса?!
52. Art Sviat (ArtemiFD) 03.03.13 22:27
(6) Yashazz, так же пользуюсь заменой условия, но предпочитаю использовать сравнения одинаковых цифр или символов.

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
 |   Учет.Товар,
 |   Учет.Количество
 |ИЗ
 |   Документ.Учет КАК Учет
 |ГДЕ
 | 1=1 
 | И 2=2";
СтрЗаменить(Запрос.Текст,"1=1","Товар = &УсловныйТовар");
...Показать Скрыть
N_aix; kastortroy2006; +2 Ответить 1
53. Яков Коган (Yashazz) 03.03.13 23:25
(52) Красиво! Спасибо за идею. В случае 666=666 вероятность совпадения практически нулевая, и читаться конструктором будет в большем количестве случаев. :)
54. ta44ik (ta44ik) 22.05.13 07:10
Еще необходима статья как заменить &ПустаяСсылка на ЗНАЧЕНИЕ(Документ.ПустаяСсылка) И &ПустаяДата например на Год(&Дата)=1(есть варианты.)
55. Евгения Карук (ekaruk) 13.10.14 13:26
Могу предложить еще вариант

СхемаЗапроса = Новый СхемаЗапроса;
СхемаЗапроса.УстановитьТекстЗапроса(Запрос.Текст);
СхемаЗапроса.ПакетЗапросов[0].Операторы[0].Отбор.Добавить("Учет.Склад = &Склад");
Запрос.Текст = СхемаЗапроса.ПолучитьТекстЗапроса();

Подробнее тут http://infostart.ru/public/307045/
56. Александр Лапшин (zfilin) 14.10.14 13:10
(55) ekaruk, Тоже хорошо. Жаль, что только для новых версий.
57. Марина Семёнова (SemenovaMarinaV) 28.10.14 11:47
58. Александр Волощук (_Sasha_) 15.06.15 09:05
А я как то к циферкам в качестве базы для замены привык.


Запрос.Текст =
"ВЫБРАТЬ РАЗРЕШЕННЫЕ
| _АСИТ_РазделкаОбороты.Разделка КАК Документ,
| _АСИТ_РазделкаОбороты.Номенклатура КАК Номенклатура,
| _АСИТ_РазделкаОбороты.НоменклатураСырье КАК НоменклатураСырье,
| _АСИТ_РазделкаОбороты.КоличествоСырьеОборот КАК Приход,
| _АСИТ_РазделкаОбороты.КоличествоПФОборот КАК Выход,
| _АСИТ_РазделкаОбороты.СуммаСырьяОборот КАК СуммаПриход,
| _АСИТ_РазделкаОбороты.СуммаПФОборот,
| _АСИТ_РазделкаОбороты.КоличествоПотериОборот КАК КоличествоПотери,
| _АСИТ_РазделкаОбороты.Потери КАК НормаПотерь
|ИЗ
| РегистрНакопления._АСИТ_Разделка.Обороты(
| &НачалоПериода,
| &КонецПериода,
| Авто,
| 1 = 1
| И 2 = 2
| И 3 = 3
| И 4 = 4) КАК _АСИТ_РазделкаОбороты
|
|УПОРЯДОЧИТЬ ПО
| Документ,
| НоменклатураСырье,
| Номенклатура
|АВТОУПОРЯДОЧИВАНИЕ";

Если ЗначениеЗаполнено(ПараметрыОтчета.Номенклатура) Тогда
Если ПараметрыОтчета.Номенклатура.ЭтоГруппа Тогда
Запрос.текст = СтрЗаменить(Запрос.Текст,"1 = 1", "Номенклатура В Иерархии(&Номенклатура)");
ОбластьМакетаШапкаНомер.Параметры.Номенклатура = "В группе " + СокрЛП(ПараметрыОтчета.Номенклатура);
Иначе
Запрос.текст = СтрЗаменить(Запрос.Текст,"1 = 1", "Номенклатура = &Номенклатура");
ОбластьМакетаШапкаНомер.Параметры.Номенклатура = ПараметрыОтчета.Номенклатура;
КонецЕсли;
Запрос.УстановитьПараметр("Номенклатура", ПараметрыОтчета.Номенклатура);

Иначе
ОбластьМакетаШапкаНомер.Параметры.Номенклатура = "По всем полуфабрикатам";
КонецЕсли;
Если ЗначениеЗаполнено(ПараметрыОтчета.НоменклатураСырье) Тогда
Если ПараметрыОтчета.НоменклатураСырье.ЭтоГруппа Тогда
Запрос.текст = СтрЗаменить(Запрос.Текст,"2 = 2", "НоменклатураСырье В Иерархии(&НоменклатураСырье)");
ОбластьМакетаШапкаНомер.Параметры.НоменклатураСырье = "В группе " + СокрЛП(ПараметрыОтчета.НоменклатураСырье);
Иначе
Запрос.текст = СтрЗаменить(Запрос.Текст,"2 = 2", "НоменклатураСырье = &НоменклатураСырье");
ОбластьМакетаШапкаНомер.Параметры.НоменклатураСырье = ПараметрыОтчета.НоменклатураСырье;
КонецЕсли;
Запрос.УстановитьПараметр("НоменклатураСырье", ПараметрыОтчета.НоменклатураСырье);

Иначе
ОбластьМакетаШапкаНомер.Параметры.НоменклатураСырье = "По всем полуфабрикатам";
КонецЕсли;
Если ЗначениеЗаполнено(ПараметрыОтчета.ЦехПроизводства) Тогда
Запрос.текст = СтрЗаменить(Запрос.Текст,"3 = 3", "ЦехПроизводства = &ЦехПроизводства");
ОбластьМакетаШапкаНомер.Параметры.ЦехПроизводства = ПараметрыОтчета.ЦехПроизводства;
Запрос.УстановитьПараметр("ЦехПроизводства", ПараметрыОтчета.ЦехПроизводства);
Иначе
ОбластьМакетаШапкаНомер.Параметры.ЦехПроизводства = "";
КонецЕсли;
59. Александр Лапшин (zfilin) 17.06.15 17:49
(58) _Sasha_, Циферки чем не удобно. Тем, что сидя в конструкторе запроса не понятно что за 1=1, что за 2=2. Надо идти смотреть в код.
Заменяемый параметр типа &УсловиеСклада более "говорящее" название. Можно писать что угодно, хоть &ТутСложноеУсловиеГдеПроверяетсяВходящиеНаВхождениеАИсходящи­еНаИсхождение. Синтаксису не противоречит, перед выполнением все-равно будет заменено и иллюстрирует о чем же условие.

Но и циферками, конечно тоже можно.
60. Виктор Окулов (okulus) 23.10.15 09:43
Подскажите, как в СКД сделать условное условие "МЕЖДУ &НачалоПериода И &КонецПериода"?
Для написания сообщения необходимо авторизоваться
Прикрепить файл
Дополнительные параметры ответа