рубрики: Запросы | Дата: 17 января, 2016
Абсолютно все программисты 1С сталкивались с динамическими запросами. То есть когда в зависимости от тех или иных условий текст запроса может меняться. Допустим в зависимости от какой-то переменной может меняться условие в запросе или список полей и т.д. Или текст запроса может формироваться в цикле.
Те кто работал с ЗУП наверняка сталкивались с тем, что во многих отчетах когда указывается начало и конец периода и требуется разбивка по месяцам изначально используется динамический запрос в результате выполнения, которого формируется примерно такая таблица (допустим, что мы формируем отчет за первый квартал 2016 г.):
НачалоПериода |
---|
01.01.2016 |
01.02.2016 |
01.03.2016 |
Соответственно текст запроса для формирования такой таблицы выглядит следующим образом:
"ВЫБРАТЬ
| ДАТАВРЕМЯ(2016, 1, 1) КАК НачалоПериода
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ДАТАВРЕМЯ(2016, 2, 1)
|
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ДАТАВРЕМЯ(2016, 3, 1)";
Но поскольку дата начала и окончания периода нам неизвестны заранее, текст запроса будет формироваться в цикле. Допустим, что у нас есть обработка или отчет на управляемой форме с реквизитами ДатаНачала и ДатаОкончания. Тогда код по формированию текста запроса будет выглядеть следующим образом:
ТекущаяДата = НачалоМесяца(Объект.ДатаНачала);
ТекстЗапроса = "
|ВЫБРАТЬ
| ДАТАВРЕМЯ(" + Формат(Год(ТекущаяДата), "ЧГ=") + ", " + Месяц(ТекущаяДата) + ", 1) КАК НачалоПериода";
ТекущаяДата = ДобавитьМесяц(ТекущаяДата, 1);
Пока ТекущаяДата <= Объект.ДатаОкончания Цикл
ТекстЗапроса = ТекстЗапроса + "
|ОБЪЕДИНИТЬ ВСЕ
|
|ВЫБРАТЬ
| ДАТАВРЕМЯ(" + Формат(Год(ТекущаяДата), "ЧГ=") + ", " + Месяц(ТекущаяДата) + ", 1)";
ТекущаяДата = ДобавитьМесяц(ТекущаяДата, 1);
КонецЦикла;
В свое время, когда я только начинал программировать на 1С и впервые столкнулся с необходимостью сформировать динамический запрос, то некоторое время не мог понять как же правильно, и в каких местах расставлять все эти плюсики и кавычки. И только потом до меня дошло, что текст запроса это всего лишь длинная строка текста, а знак «|» означает лишь перенос на следующую строку. И таким образом правила внедрения переменных в текст запроса те же самые, что и при работе с обычной строкой.
Теперь немного о том как писать динамические запросы быстро. Поначалу их написание приводило у меня к большим временным затратам и взрыву мозга. Ведь если взять даже пример приведенный выше, то чтобы сразу написать формирование запроса в цикле придется немножко подумать. А если итоговый запрос содержит порядка 200 строк с кучей вставок переменных(а в конфигурации ЗУП есть и по 2000 строк)? Поэтому не особо задумываясь, открываем конструктор запросов и пишем один вариант (или несколько вариантов) конечного запроса. Проверяем работоспособность в консоли запросов. Потом копируем текст запроса в процедуру, где он будет формироваться динамически и в необходимых местах заменяем текст на переменные. Ну и конечно не забываем тестировать.
А теперь рассмотрим еще один пример формирования динамического запроса.
Допустим, что в зависимости от какой то переменной нам надо выбирать данные (пусть это будут период регистрации, сотрудник и сумма) либо из регистра расчетов «ОсновныеНачисленияРаботниковОрганизаций» либо из регистра «ДополнительныеНачисленияРаботниковОрганизаций». Вот код с формированием текста:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 10
| ДанныеРегистра.ПериодРегистрации,
| ДанныеРегистра.Сотрудник,
| ДанныеРегистра.Результат
|ИЗ
| РегистрРасчета." + ?(ЭтоОсновныеНачисления, "ОсновныеНачисленияРаботниковОрганизаций", "ДополнительныеНачисленияРаботниковОрганизаций") + " КАК ДанныеРегистра";
Но можно сделать и по другому:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 10
| ДанныеРегистра.ПериодРегистрации,
| ДанныеРегистра.Сотрудник,
| ДанныеРегистра.Результат
|ИЗ
| //ТАБЛИЦА_РЕГИСТРА";
Если ЭтоОсновныеНачисления Тогда
ТекстТаблица = " РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций КАК ДанныеРегистра";
Иначе
ТекстТаблица = " РегистрРасчета.ДополнительныеНачисленияРаботниковОрганизаций КАК ДанныеРегистра";
КонецЕсли;
Запрос.Текст = СтрЗаменить(Запрос.Текст, "//ТАБЛИЦА_РЕГИСТРА", ТекстТаблица);
Последний вариант бывает иногда удобней, т.к. во-первых позволяет более легко понять структуру запроса, а во-вторых его иногда можно открыть в конструкторе запроса. В нашем случае в конструкторе запрос не откроется, т.к. таблица не указана, но вот такой откроется:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ ПЕРВЫЕ 10
| //ДОПОЛНИТЕЛЬНЫЕ_ПОЛЯ
| ДанныеРегистра.ПериодРегистрации,
| ДанныеРегистра.Сотрудник,
| ДанныеРегистра.Результат
|ИЗ
| РегистрРасчета.ОсновныеНачисленияРаботниковОрганизаций КАК ДанныеРегистра
|//УСЛОВИЯ_ЗАПРОСА
|";
Для небольшого по объему запроса существенной разницы нет, но когда он большой, то в конструкторе его анализировать гораздо удобней. Только помните, что если вы открыли такой запрос в конструкторе, ни в коем случае не нажимайте потом на кнопу «ОК», иначе все закоментированные строчки внутри запроса пропадут.
Добавить комментарий