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

25.10.10

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

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

Скачать файл

ВНИМАНИЕ: Файлы из Базы знаний - это исходный код разработки. Это примеры решения задач, шаблоны, заготовки, "строительные материалы" для учетной системы. Файлы ориентированы на специалистов 1С, которые могут разобраться в коде и оптимизировать программу для запуска в базе данных. Гарантии работоспособности нет. Возврата нет. Технической поддержки нет.

Наименование По подписке [?] Купить один файл
УсловияИЗапросы
.zip 22,93Kb
133
133 Скачать (1 SM) Купить за 1 850 руб.

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

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


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

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

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

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

10000 руб.

02.09.2020    159650    875    399    

862

Запросы Программист Бесплатно (free)

Увидел cheatsheet по SQL и захотелось нарисовать подобное, но про запросы.

18.10.2024    9937    sergey279    18    

64

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

Столкнулся с интересной ситуацией, которую хотел бы разобрать, ввиду её неочевидности. Речь пойдёт про использование функции запроса АВТОНОМЕРЗАПИСИ() и проблемы, которые могут возникнуть.

11.10.2024    5198    XilDen    36    

80

Запросы Программист Запросы Бесплатно (free)

Отлаживая взаимодействие с базой данных, мы регулярно сталкиваемся с зависающими или подозрительно долго выполняющимися обращениями, негативно влияющими на производительность. О том, как в PostgreSQL выявить подозрительные запросы, основываясь на доступной о них информации, расскажем в статье.

16.08.2024    7929    user1840182    5    

28

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

Рассмотрим быстрый алгоритм поиска дублей с использованием hash функции по набору полей шапки и табличных частей.

08.07.2024    2403    ivanov660    9    

22

Запросы СКД Программист Стажер Система компоновки данных Россия Бесплатно (free)

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

15.05.2024    8719    implecs_team    6    

47

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

Часто поступают задачи по произвольному распределению общих сумм. После распределения иногда пропадают копейки. Суть решения добавить АвтоНомерЗаписи() в ВТ распределения, и далее используя функции МАКСИМУМ или МИНИМУМ можем положить разницу копеек в первую или последнюю строку знаменателя распределения.

11.04.2024    3392    andrey_sag    10    

36
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. alexk-is 6544 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 2352 19.10.10 10:09 Сейчас в теме
(4) Ага. Точно!

(1) Насчет "Учет.Склад.Ссылка = " согласен, это я "очепятался". И спасибо, что предложили еще более совершенный способ достигнуть требуемого результата. Правда, я не совсем понял при чем тут ваш замечательны журнал, но видимо какая-то связь есть...
Monte Carlo; +1 Ответить
6. Yashazz 4791 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; 1CEnterprise; 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 4791 03.03.13 23:25 Сейчас в теме
(52) Красиво! Спасибо за идею. В случае 666=666 вероятность совпадения практически нулевая, и читаться конструктором будет в большем количестве случаев. :)
user1937902; +1 Ответить
7. 4ish 19.10.10 10:41 Сейчас в теме
Еще как вариант:

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

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

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



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

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

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

Я делаю так:

Нахожу строчку Запрос.выполнить(). Ставлю точку останова и перехожу в отладку. Когда точка срабатывает, делаю следующее:
Нажимаю на кнопку "Вычислить выражение";
в поле пишу Запрос.Текст (если через построитель то ПостроительОтчета.ПолучитьЗапрос().Текст);
Копирую текст запроса и отлаживаю его в консоли.
О.Ж; InJey; Lena272; sanfoto; NazarovV; МимохожийОднако; dandrontiy; +7 Ответить
19. zfilin 2352 20.10.10 14:32 Сейчас в теме
(16) Спасибо за подсказку, я тоже использую такой способ для отладки. =)
21. I_G_O_R 69 20.10.10 22:44 Сейчас в теме
(16) Вы наверное большие запросы не видели, в ЗУПе они почему-то не помещаются :cry:
22. artbear 1563 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 2352 20.10.10 14:13 Сейчас в теме
О! Спасибо всем, сколько способов!
Нужно обязательно будет включить их в текст самой статьи.
20. mst 20.10.10 14:55 Сейчас в теме
а я в 7ке пишу не "=" а "в" и работает независимо выбран элемент или нет... никогда не писал =, потому что при "в" в запрос попадают еще и элементы из подгрупп выбранной группы справочника.
24. Lapitskiy 1061 22.10.10 14:16 Сейчас в теме
с выводами по скорости не согласен, если выполнять запросы в цикле, выборка идет из кэша! Надо не запрос в цикле делать, а 1 запрос по большой базе.
25. zfilin 2352 22.10.10 14:24 Сейчас в теме
(24) Согласен, я для этого и приложил конфу, чтобы можно было по-разному попробовать.
26. rasswet 82 22.10.10 16:53 Сейчас в теме
в если из ГДЕ Учет.Склад.Ссылка убрать ссылку?
27. zfilin 2352 22.10.10 18:30 Сейчас в теме
(26) Про ссылку еще в самом начале говорили, она там случайно оказалась.
Наверное, надо подредаткировать...
29. Yashazz 4791 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 194 21.02.11 15:05 Сейчас в теме
(0) добавлю свои пять копеек. Похоже на уже описанные тут варианты..

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

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


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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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


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

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

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

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


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

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

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

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

Подробнее тут http://infostart.ru/public/307045/
antonio_i; kasper076; +2 Ответить
56. zfilin 2352 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 2352 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 Сейчас в теме
У меня такое условие выдает ошибку.
	|ГДЕ
	|	ГрафикиРаботы.Сотрудник = &Сотрудник
	|	И (&Кабинет = ЗНАЧЕНИЕ(Справочник.Оборудование.ПустаяСсылка)
	|			ИЛИ ГрафикиРаботы.Кабинет = &Кабинет)
	|	И (&Филиал = ЗНАЧЕНИЕ(Справочник.Филиалы.ПустаяСсылка)
	|			ИЛИ ГрафикиРаботы.Филиал = &Филиал)

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

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