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

25.10.10

Разработка - Запросы

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

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

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

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

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


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

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

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

 

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

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

 

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

См. также

SALE! 20%

Infostart Toolkit: Инструменты разработчика 1С 8.3 на управляемых формах

Инструментарий разработчика Роли и права Запросы СКД Платформа 1С v8.3 Управляемые формы Запросы Система компоновки данных Конфигурации 1cv8 Платные (руб)

Набор инструментов программиста и специалиста 1С для всех конфигураций на управляемых формах. В состав входят инструменты: Консоль запросов, Консоль СКД, Консоль кода, Редактор объекта, Анализ прав доступа, Метаданные, Поиск ссылок, Сравнение объектов, Все функции, Подписки на события и др. Редактор запросов и кода с раскраской и контекстной подсказкой. Доработанный конструктор запросов тонкого клиента. Продукт хорошо оптимизирован и обладает самым широким функционалом среди всех инструментов, представленных на рынке.

13000 10400 руб.

02.09.2020    121546    670    389    

709

Для чего используют конструкцию запроса "ГДЕ ЛОЖЬ" в СКД на примере конфигурации 1С:ERP

Запросы СКД Платформа 1С v8.3 Запросы Система компоновки данных 1С:ERP Управление предприятием 2 Бесплатно (free)

В типовых конфигурациях разработчики компании 1С иногда используют в отчетах, построенных на СКД, такую конструкцию, как "ГДЕ ЛОЖЬ". Такая конструкция говорит о том, что данные в запросе не будут получены совсем. Для чего же нужен тогда запрос?

13.02.2024    5738    KawaNoNeko    23    

23

Набор-объект для СКД по тексту или запросу

Запросы СКД Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Есть список полей в виде текста, или запрос - закидываем в набор СКД.

1 стартмани

31.01.2024    1996    2    Yashazz    0    

29

Запрос 1С copilot

Инструментарий разработчика Запросы Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Абонемент ($m)

Пишем на человеческом языке, что нам надо, и получаем текст запроса на языке 1С. Используются большие языковые модели (LLM GPT) от OpenAI или Яндекс на выбор.

5 стартмани

15.01.2024    6275    30    mkalimulin    25    

49

PrintWizard: поддержка представлений ЗУП в конструкторе

Инструментарий разработчика Запросы Платформа 1С v8.3 Бесплатно (free)

Одной из интересных задач, стоящих в процессе разработки, была поддержка механизма представлений в ЗУП. Но не просто возможность исполнения запросов с ними. Основная проблема была в том, чтобы с ними было удобно работать, а именно: создавать, модифицировать и отлаживать. Кратко о том, что в итоге получилось...

14.12.2023    1739    vandalsvq    7    

29

Объектная модель запроса "Схема запроса" 2

Запросы Платформа 1С v8.3 Запросы Конфигурации 1cv8 Бесплатно (free)

Далеко уже не новый тип данных "Схема запроса". Статья о том, как использовать его "попроще". Примеры создания текста запроса с нуля и изменение имеющегося запроса.

06.12.2023    5380    user1923546    26    

43

Начните уже использовать хранилище запросов

HighLoad оптимизация Запросы

Очень немногие из тех, кто занимается поддержкой MS SQL, работают с хранилищем запросов. А ведь хранилище запросов – это очень удобный, мощный и, главное, бесплатный инструмент, позволяющий быстро найти и локализовать проблему производительности и потребления ресурсов запросами. В статье расскажем о том, как использовать хранилище запросов в MS SQL и какие плюсы и минусы у него есть.

11.10.2023    16154    skovpin_sa    14    

98
Комментарии
В избранное Подписаться на ответы Сортировка: Древо развёрнутое
Свернуть все
1. alexk-is 6533 19.10.10 05:27 Сейчас в теме
Может так?

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


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

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

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

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

Конечно, конструктор режет комментарии, но хоть прочитать запрос при этом может.
15. Alias 176 19.10.10 17:27 Сейчас в теме
(6) А я пишу так. Конструктор отрабатывает без проблем, ничего не теряется... и сама строка "&УсловиеСклада" выглядит понятнее чем какие-то сложные условия. И выполнение запроса (это важно!) при этом не тормозит. И конструктор ничего не режет. Короче, сплошные плюсы :)

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

Запрос.Текст = СтрЗаменить(Запрос.Текст, "&УсловиеСклада",?(ЗначениеЗаполнено(ВыбСклад),"Учет.Склад.Ссылка = &Склад",""));
G_117106206056832682599; Summer_13; InJey; Monte Carlo; marlonix; Innuil; zfilin; gaglo; tango; valm0unt; +10 Ответить
18. gaglo 20.10.10 14:16 Сейчас в теме
(15) Тут не понял: если "&УсловиеСклада" заменить на "", то получится запрос
"ВЫБРАТЬ
...
|ГДЕ ";
- но ведь он синтаксически неверен?

Я пишу почти так же, только вместо "ГДЕ &УсловиеСклада" ставлю "ГДЕ Истина".
Выглядит не так уж понятно, и наводит на не те мысли (сравни с "Где справедливость?")
Зато можно выполнять и без всяких СтрЗаменить...
Summer_13; cute_sky_1C; Alias; +3 Ответить
23. Alias 176 21.10.10 11:54 Сейчас в теме
(18) Ой, конечно, Вы абсолютно правы! Поспешил с написанием комментария. У меня просто обычно этот приём используется как часть сложного условия (то есть, например, условие на Организацию есть всегда). Тогда пустой строки никак не бывает.

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

Выбор варианта зависит от удобства в конкретном случае.
62. G_117106206056832682599 25.03.21 19:59 Сейчас в теме
(15) Отлично! Так в методических рекомендациях и написано.
52. ArtemiFD 42 03.03.13 22:27 Сейчас в теме
(6) Yashazz, так же пользуюсь заменой условия, но предпочитаю использовать сравнения одинаковых цифр или символов.

Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
 |   Учет.Товар,
 |   Учет.Количество
 |ИЗ
 |   Документ.Учет КАК Учет
 |ГДЕ
 | 1=1 
 | И 2=2";
СтрЗаменить(Запрос.Текст,"1=1","Товар = &УсловныйТовар");
Показать
RodinMax; Suslik_Johns; Светлый ум; N_aix; kastortroy2006; +5 Ответить
53. Yashazz 4709 03.03.13 23:25 Сейчас в теме
(52) Красиво! Спасибо за идею. В случае 666=666 вероятность совпадения практически нулевая, и читаться конструктором будет в большем количестве случаев. :)
user1937902; +1 Ответить
7. 4ish 19.10.10 10:41 Сейчас в теме
Еще как вариант:

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

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

(1) А! Спасибо, уже оценил!
9. alexk-is 6533 19.10.10 11:05 Сейчас в теме
(8) По ссылке в (1) используется много разных запросов. Мой любимый по структуре подчиненности документов.
10. zfilin 2337 19.10.10 11:11 Сейчас в теме
(9) Ага, вот смотрю как раз. Круто, че сказать.
11. artbear 1448 19.10.10 13:39 Сейчас в теме
По опыту скажу:
1. Построитель не всегда удобен :(
2. использование как (0), так и (7) не всегда удобно.
Лично я чаще юзаю сравнение не с ПустаяСсылка, а с NULL.
cute_sky_1C; +1 Ответить
12. artbear 1448 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 2337 19.10.10 14:04 Сейчас в теме
(12) О! Спасибо, тестирование меня очень интересует, обязательно посмотрю.
14. Vit aka proger 105 19.10.10 16:34 Сейчас в теме
а я обычно пишу так:
Запрос.Текст =
"ВЫБРАТЬ
| Учет.Товар,
| Учет.Количество
|ИЗ
| Документ.Учет КАК Учет
|ГДЕ
| Учет.Склад в иерархии( &Склад))";
Если склад пустой, выбирается по всем имеющимся складам



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

marlonix; happy_saint; zfilin; gaglo; +4 Ответить
30. Serj1C 483 26.10.10 09:08 Сейчас в теме
(14) "в иерархии" работает медленно!

мне больше нравится (1) и (15)
16. Minotavrik 1634 20.10.10 10:51 Сейчас в теме
Есть хороший способ отлаживать большие и страшные, текст которых изменен в конфигураторе различными операторами.

Я делаю так:

Нахожу строчку Запрос.выполнить(). Ставлю точку останова и перехожу в отладку. Когда точка срабатывает, делаю следующее:
Нажимаю на кнопку "Вычислить выражение";
в поле пишу Запрос.Текст (если через построитель то ПостроительОтчета.ПолучитьЗапрос().Текст);
Копирую текст запроса и отлаживаю его в консоли.
InJey; Lena272; sanfoto; NazarovV; МимохожийОднако; dandrontiy; +6 Ответить
19. zfilin 2337 20.10.10 14:32 Сейчас в теме
(16) Спасибо за подсказку, я тоже использую такой способ для отладки. =)
21. I_G_O_R 69 20.10.10 22:44 Сейчас в теме
(16) Вы наверное большие запросы не видели, в ЗУПе они почему-то не помещаются :cry:
22. artbear 1448 21.10.10 07:13 Сейчас в теме
(21) Все помещается, нужно только включить выражение с текстом в табло просмотра, далее щелкнуть на тексте, и нажать лупу. откроется окошко для просмотра текста, откуда и можно скопировать текст.

(16) (19) Копирование текста запроса вручную неудобно, т.к. параметры придется самому ставить :(
лучше пользоваться спец.консолями, которые могут отлаживать сам запрос.
В итоге в отладчике вычисляешь код Отладить(Запрос) и в режиме Предприятия открывается консоль с полным запросом (текст, параметры, временные таблицы и т.д.)
Посмотрите мою разработку http://infostart.ru/public/65526/
В ней я описал различные фичи, в т.ч. и мощнейшие консоли.
28. I_G_O_R 69 22.10.10 22:58 Сейчас в теме
(22) я именно так и смотрю, просто в ЗУПе есть такие большие запросы что в этом окне только часть текста (например текст запроса расчета НДФЛ, в нем около 5000 строк, а помещается где-то 3000 с лишним).
17. zfilin 2337 20.10.10 14:13 Сейчас в теме
О! Спасибо всем, сколько способов!
Нужно обязательно будет включить их в текст самой статьи.
20. mst 20.10.10 14:55 Сейчас в теме
а я в 7ке пишу не "=" а "в" и работает независимо выбран элемент или нет... никогда не писал =, потому что при "в" в запрос попадают еще и элементы из подгрупп выбранной группы справочника.
24. Lapitskiy 1057 22.10.10 14:16 Сейчас в теме
с выводами по скорости не согласен, если выполнять запросы в цикле, выборка идет из кэша! Надо не запрос в цикле делать, а 1 запрос по большой базе.
25. zfilin 2337 22.10.10 14:24 Сейчас в теме
(24) Согласен, я для этого и приложил конфу, чтобы можно было по-разному попробовать.
26. rasswet 82 22.10.10 16:53 Сейчас в теме
в если из ГДЕ Учет.Склад.Ссылка убрать ссылку?
27. zfilin 2337 22.10.10 18:30 Сейчас в теме
(26) Про ссылку еще в самом начале говорили, она там случайно оказалась.
Наверное, надо подредаткировать...
29. Yashazz 4709 25.10.10 15:00 Сейчас в теме
Способ Alias'a опасен тем, что при достаточно сложной логике условия есть риск запутаться и налажать. Простыми "истина" и "ложь" тоже можно напутать - поставить, например, "Истина" в условие "И", а потом поменять где-то что-то на "Или", условие-то большое, и получить ошибку.
31. Alias 176 26.10.10 09:24 Сейчас в теме
(29) Не согласен. Разбивание большого и сложного условия на несколько маленьких наоборот, упростит понимание условия! Сравните, например, один из предложенных вариантов:

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

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

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

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

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

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

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


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

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

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

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

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

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

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

P.S. Вопрос снят. Разобрался.
41. пользователь 07.08.12 15:36
Сообщение было скрыто модератором.
...
42. Altair777 644 07.08.12 15:37 Сейчас в теме
(38)

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

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

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

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

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

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

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

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

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

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


Чем же оно гораздо затратнее получается, может, я не заметил чего?.. =(
47. Altair777 644 07.08.12 18:29 Сейчас в теме
(45)
как-то так :)

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

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

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


А если условие стоит в середине текста (вложенные запросы)? Хоть вешайся.
50. zfilin 2337 07.08.12 18:39 Сейчас в теме
(47) Да, добавлением не очень удобно.
(49) Свои минусы есть. В консоли отлаживать не очень удобно, но как вы справедливо заметили для отладки лучше использовать итоговый текст из строки "Выполнить()". =) Раз уж мы тут все замешаны в выдаче страшных секретов. =)))
51. AlexO 135 08.08.12 10:13 Сейчас в теме
(50)
вся проблема - даже не в получить окончательный текст запроса (хотя он и будет в каждом другом случае - разный), а собрать размазанные параметры, чтобы воспроизвести в консоли именно текущий запрос.
Это проблема проблем :)
Я решаю совсем уж оригинальным способом, здесь не указанным.
(48) Altair777,
я отредактировал цитату, теперь ваша очередь :)
но вдруг уже попала в поисковую базу яндекса?!
49. Altair777 644 07.08.12 18:34 Сейчас в теме
(45)

понял! А если этот текст перекинуть в консоль запросов, то как его отлаживать?
Два понятных параметра НачалоПериода И КонецПериода заменяется на нечто... совсем не понятное :)
46. AlexO 135 07.08.12 18:22 Сейчас в теме
(42) Altair777,
лучше в отладчике отловить окончательный текст ....

оо, выдал все профессиональные тайны ... :(
48. Altair777 644 07.08.12 18:30 Сейчас в теме
(46) AlexO, да?!!! :)
Я бы мог отредактировать свой коммент чтобы не раскрывать тайну, но... все равно останется в цитате.
40. AlexO 135 07.08.12 15:35 Сейчас в теме
Непонятны восторги.
Ну да, хорошо, собрал в одном месте варианты проверок (да и то не все), - но не систематизированные, без описания применимости и раскрытия смысла.
Есть масса способов сделать условие в запросе.
Их уже множество тут накидали.
1С наделала столько всего, что оно и не нужно так много. Достаточно было сделать одно - но путное и быстрое.
Можно и ВЫБОР...КОГДА, можно и через параметр &Параметр, можно и заменой текста запроса перед выполнением.
ПостроительОтчета для выполнения запроса используют только тру-1сники.
А все же посыл статьи не раскрыт: без динамического формирования запросов во многих случаях не обойтись никак, ничем это не заменишь, и никаких инструментов в 1С для отладки нет.
54. ta44ik 57 22.05.13 07:10 Сейчас в теме
Еще необходима статья как заменить &ПустаяСсылка на ЗНАЧЕНИЕ(Документ.ПустаяСсылка) И &ПустаяДата например на Год(&Дата)=1(есть варианты.)
55. ekaruk 4896 13.10.14 13:26 Сейчас в теме
Могу предложить еще вариант

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

Подробнее тут http://infostart.ru/public/307045/
antonio_i; kasper076; +2 Ответить
56. zfilin 2337 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", "ЦехПроизводства  = &ЦехПроизводства");
		ОбластьМакетаШапкаНомер.Параметры.ЦехПроизводства = ПараметрыОтчета.ЦехПроизводства;	
		Запрос.УстановитьПараметр("ЦехПроизводства", 	ПараметрыОтчета.ЦехПроизводства);
	Иначе
		ОбластьМакетаШапкаНомер.Параметры.ЦехПроизводства = "";	
	КонецЕсли; 
Показать
Светлый ум; +1 Ответить
59. zfilin 2337 17.06.15 17:49 Сейчас в теме
(58) _Sasha_, Циферки чем не удобно. Тем, что сидя в конструкторе запроса не понятно что за 1=1, что за 2=2. Надо идти смотреть в код.
Заменяемый параметр типа &УсловиеСклада более "говорящее" название. Можно писать что угодно, хоть &ТутСложноеУсловиеГдеПроверяетсяВходящиеНаВхождениеАИсходящи­еНаИсхождение. Синтаксису не противоречит, перед выполнением все-равно будет заменено и иллюстрирует о чем же условие.

Но и циферками, конечно тоже можно.
Дмитрий74Чел; +1 Ответить
60. okulus 23.10.15 09:43 Сейчас в теме
Подскажите, как в СКД сделать условное условие "МЕЖДУ &НачалоПериода И &КонецПериода"?
61. ToJIuK 28.10.19 15:40 Сейчас в теме
Это все работает когда запрос пишется в модуле . А как быть если мне нужно данное условие засунуть в "ДинамическийСписок" через параметры формы
Пробовал
ЗНАЧЕНИЕ(Справочник.

Пишет ошибку . "Не понимает "?Справочник" ".
Пробовал передать пустое значение "Контрагента" (я по Контрагенту фильтрую) выходит пустой отбор . Подскажите как быть ? как сделать так чтобы условие работало только когда передан Контрагент
63. dyahon 01.10.21 11:59 Сейчас в теме
Конкретно здесь, поступил бы развивая первый вариант:

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

ИЛИ - выносится в отдельный запрос (справочник склад обычно небольшой)

"ВЫБРАТЬ
|	Склады.Ссылка КАК Склад
|ПОМЕСТИТЬ вт_СкладыДляОстатков
|ИЗ
|	Справочник.Склады КАК Склады
|ГДЕ
|	(Склады.Ссылка = &Ссылка
|			ИЛИ Склады.Ссылка = ЗНАЧЕНИЕ(Справочник.Склады.ПустаяСсылка))
|;
|
|////////////////////////////////////////////////////////////­////////////////////
|ВЫБРАТЬ
|	РеализацияТоваровУслуг.Количество КАК Количество,
|	вт_СкладыДляОстатков.Склад КАК Склад,
|ИЗ
|	втСкладыДляОстатков КАК втСкладыДляОстатков
|		ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
|		ПО вт_СкладыДляОстатков.Склад = РеализацияТоваровУслуг.Склад
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
|	ТоварыНаСкладеОстатки.Количество,
|	ТоварыНаСкладеОстатки.Склад
|ИЗ
|	РегистрНакопления.ТоварыНаСкладе.Остатки(
|			,
|			Склад В
|				(ВЫБРАТЬ
|					вт_СкладыДляОстатков.Склад
|				ИЗ
|					вт_СкладыДляОстатков)) КАК ТоварыНаСкладеОстатки
Показать
64. baracuda 2 27.05.23 14:15 Сейчас в теме
У меня такое условие выдает ошибку.
	|ГДЕ
	|	ГрафикиРаботы.Сотрудник = &Сотрудник
	|	И (&Кабинет = ЗНАЧЕНИЕ(Справочник.Оборудование.ПустаяСсылка)
	|			ИЛИ ГрафикиРаботы.Кабинет = &Кабинет)
	|	И (&Филиал = ЗНАЧЕНИЕ(Справочник.Филиалы.ПустаяСсылка)
	|			ИЛИ ГрафикиРаботы.Филиал = &Филиал)

Лечится так
	//Установка значений параметров
	Запрос.УстановитьПараметр("Сотрудник", Объект.Ссылка);
	Если ЗначениеЗаполнено(ЭтаФорма.КабинетЛек) Тогда 
		Запрос.УстановитьПараметр("Кабинет", ЭтаФорма.КабинетЛек);
	Иначе
		Запрос.УстановитьПараметр("Кабинет", Справочники.Оборудование.ПустаяСсылка());
	КонецЕсли;
	
	Если ЗначениеЗаполнено(ЭтаФорма.ФилиалЛек) Тогда 
		Запрос.УстановитьПараметр("Филиал", ЭтаФорма.ФилиалЛек);
	Иначе
		Запрос.УстановитьПараметр("Филиал", Справочники.Филиалы.ПустаяСсылка());
	КонецЕсли;
Показать

но тогда в чем профит не понимаю, мне казалось что параметры не обзяательно устнавливать. но нсли не установить падается ошибка не установки параметра.
Оставьте свое сообщение