Как известно основой работы по отбору данных на платформе 1С-Предприятие 8.х являются запросы, в этом кратком материале, не претендующем на полноту, приводится несколько простых приёмов работы с запросами на мой взгляд, представляющих интерес для новичков. Все приёмы будут приводиться в тексте запросов, после кода будет даваться краткое пояснение. Большинство приёмов рассчитаны на традиционную парадигму кодирования на 1С8.Х, а именно: вынесение многократно используемого кода в общие модули, стремление к написанию более компактного и более читаемого кода, написание универсальных процедур и функций. Запросы выбраны для примеров самые простые, что-бы лучше был виден сам приём а не терялся в глубине кода.
1. 1.Обработка пустого результата в самом запросе.
Запрос.Текст = "ВЫБРАТЬ
| Номенклатура.Ссылка,
| ЕСТЬNULL(ОстаткиНоменклатурыОстатки.КоличествоОстаток,0)
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
| ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ОстаткиНоменклатуры.Остатки(&МоментВремени, )
| КАК ОстаткиНоменклатурыОстатки
| ПО ОстаткиНоменклатурыОстатки.Номенклатура = Номенклатура.Ссылка"
Что это даёт: в результате работы запрос может возвращать значение типа «Null». В этом случае работа с результатом запроса выдаст ошибку, т.к. значение типа "Null" не может быть преоблазовано к значению другого вида (число, строка и др.). Функция ЕСТЬNULL() прямо в запросе произведёт проверку возвращаемого результата. Такой приём позволяет несколько разгрузить клиентскую часть, в случае многократного использования запроса вынесенного в общий модуль позволит сократить строки кода.
2.Построение многовариантного запроса.
Процедура ОбщийОтбор(Тип, МоментВремени)
Запрос.Текст ="ВЫБРАТЬ
| ОстаткиНоменклатурыОстатки.КоличествоОстаток
|ИЗ
| РегистрНакопления.ОстаткиНоменклатуры.Остатки(&МоментВремени, ) КАК |ОстаткиНоменклатурыОстатки"
Если Тип=1 Тогда
СтрЗаменить(Запрос.Текст," .ОстаткиНоменклатуры.", ".ОстаткиИмущества.");
КонецЕсли;
Результат = Запрос.Выполнить();
Что это даёт: выполнение над текстом запроса операции «СтрЗаменить» до команды «Запрос.Выполнить()» позволяет сделать универсальный и легко читаемый запрос над разными схожими по структуре регистрами. Конечно, можно было вынести имя регистра в переменную ну например «ИмяРегистра» тогда-бы запрос имел вид :
"ВЫБРАТЬ
| ОстаткиНоменклатурыОстатки.КоличествоОстаток
|ИЗ
| РегистрНакопления. "+ИмяРегистра+".Остатки(&МоментВремени, ) КАК |ОстаткиНоменклатурыОстатки"
Но в этом случае мы теряем возможность правки текста запроса посредством конструктора запросов, что в случае сложных запросов является серьёзным недостатком
3. Использование функции Значение.
"ВЫБРАТЬ
КонтактСКлиентом.Контрагент,
КонтактСКлиентом.ВидКонтакта,
КонтактСКлиентом.Заголовок,
КонтактСКлиентом.Тема,
КонтактСКлиентом.МоментВремени
ИЗ
Документ.КонтактСКлиентом КАК КонтактСКлиентом
ГДЕ
КонтактСКлиентом.ВидКонтакта = ЗНАЧЕНИЕ(Перечисление.ВидыКонтактов.Звонок)"
Что это даёт: если этот запрос отбирает только один вид контакта, то нет необходимости передавать вид контакта в качестве параметра в запрос.
Примечение: в качестве аргумента функции значение может выступать предопределённое значение, т.е то значение, к которому кожно обратиться из кода напрямую (предопределённые счета плана счетов, все значения перечислений и т.п.).
4. Выгрузка результатов запроса в табличную часть.
Запрос.Текст = "ВЫБРАТЬ
| ПоступлениеТоваров.Номенклатура КАК Номенклатура,
| СУММА(ПоступлениеТоваров.Количество) КАК Количество,
| СУММА(ПоступлениеТоваров.Сумма) КАК Сумма,
| ПоступлениеТоваров.Ссылка.Дата КАК Период,
| ПоступлениеТоваров.Ссылка.Контрагент КАК Контрагент
| ИЗ
| Документ.ПриобретениеТМЦ.РеестрТМЦ КАК ПоступлениеТоваров
| ГДЕ
| ПоступлениеТоваров.Ссылка = &Ссылка
| СГРУППИРОВАТЬ ПО
| ПоступлениеТоваров.Номенклатура,
| ПоступлениеТоваров.Ссылка.Контрагент";
ТаблицаЗакупок = Запрос.Выполнить().Выгрузить();
Движения.Закупки.Загрузить(ТаблицаЗакупки);
Что это даёт: такой код позволяет выполнить загрузку результатов запроса в табличную часть документа двумя командами без обхода результатов в цикла. Код более компактный, читабельный, быстрый.
5. Добавление необходимых значений в результат запроса.
При использовании результатов запроса, как в предыдущем примере, нередко для получения значения некоторых колонок в запрос приходится добавлять обращения ещё к одной или нескольким таблицам, чтобы получить значения всех требуемых колонок, в том случае когда эти значения уже известны их можно передать в качестве параметров, подобный запрос может иметь вид:
Запрос.Текст = "ВЫБРАТЬ
| ПоступлениеТоваров.Номенклатура КАК Номенклатура,
| СУММА(ПоступлениеТоваров.Количество) КАК Количество,
| СУММА(ПоступлениеТоваров.Сумма)КАК Сумма,
| &ДатаПриобретения КАК Период,
| &Поставщик КАК Контрагент
|ИЗ
| Документ.ПриобретениеТМЦ.РеестрТМЦ КАК ПоступлениеТоваров
|ГДЕ
| ПоступлениеТоваров.Ссылка = &Ссылка
|СГРУППИРОВАТЬ ПО
| ПоступлениеТоваров.Номенклатура;"
Запрос.УстановитьПараметр("ДатаПриобретения", ДатаОтбора);
Запрос.УстановитьПараметр("Поставщик",ВыбраныйПоставщик);
ТаблицаЗакупок = Запрос.Выполнить().Выгрузить();
Движения.Закупки.Загрузить(ТаблицаЗакупки);
Что это даёт: читабьельность не теряется, запрос удобнее читается «с экрана», за счёт ухода от использования в запросе обращения к дополнительным таблицам, время выполнения запроса меньше.
6. Передача массива в качестве параметра.
"ВЫБРАТЬ
| КонтактСКлиентом.Контрагент,
| КонтактСКлиентом.ВидКонтакта,
| КонтактСКлиентом.Заголовок,
| КонтактСКлиентом.Тема,
| КонтактСКлиентом.МоментВремени
|ИЗ
| Документ.КонтактСКлиентом КАК КонтактСКлиентом
|ГДЕ
| КонтактСКлиентом.ВидКонтакта В (&ВидыКонтактов)"
ВидыКонтактов = Новый Массив;
ВидыКонтактов.Добавить(Перечисления.ВидыКонтактов.Звонок);
ВидыКонтактов.Добавить(Перечисления.ВидыКонтактов.Письмо);
ВидыКонтактов.Добавить(Перечисления.ВидыКонтактов.Встреча);
Запрос.УстановитьПараметр("ВидыКонтактов ", ВидыКонтактов);
Что это даёт: текст запроса остаётся читабельным, количество параметров не зашкаливает, трафик данных между клиентом и сервером минимальный.
7.По многочисленным просьбам пример чуть посложнее, результат запроса будет выгружен в регист остатков.
Текст, демонстрирующий сразу несколько приёмов, текст кода находится в модуле объекта документа (естественно в оригинале код немного сложнее и движения выполняются по нескольким регистрам), код написан для платформы 1С8.2 :
Процедура ОбработкаПроведения(Отказ, РежимПроведения)
Движения.ОстаткиНоменклатуры.Записывать = Истина;
ВыполнитьДвиженияОстаткиНоменклатуры();
КонецПроцедуры
Процедура ВыполнитьДвиженияОстаткиНоменклатуры() Экспорт
Запрос = Новый Запрос;
Запрос.Текст =" ВЫБРАТЬ
| РеализацияТоваровТовары.Номенклатура,
| РеализацияТоваровТовары.Сумма,
| РеализацияТоваровТовары.Качество,
| РеализацияТоваровТовары.Ссылка.Дата КАК Период,
| ЗНАЧЕНИЕ(ВидДвиженияНакопления.Расход) КАК ВидДвижения
| ИЗ
| Документ.РеализацияТоваров.Товары КАК РеализацияТоваровТовары
| ГДЕ
| РеализацияТоваровТовары.Ссылка =&Ссылка
| И РеализацияТоваровТовары.Номенклатура.ВидНоменклатуры <> Значение(Перечисления.ВидыНоменкклатуры.Услуга)";
Запрос.УстановитьПараметр("Ссылка", Ссылка);
Результат = Запрос.Выполнить();
Движения.ОстаткиНоменклатуры.Загрузить(Результат.Выгрузить());
Движения.ОстаткиНоменклатуры.Записать();
КонецПроцедуры
Что делает этот код: процедура "ОбработкаПроведения" вызывает процедуру "ВыполнитьДвиженияОстаткиНоменклатуры" (Далее просто процедура). Процедура выполняет запрос, с единственным параметром "Ссылка" (это ссылка на наш документ - выполняющий функцию регистратора движений регистра). Запрос возвращет весь перечень номенклатуры документа кроме номеклатуры имеющей тип "Услуга", результат запроса выгружается в таблицу и из таблицы загружается в регистр "РегистрыНакопления.ОстаткиНоменклатуры"(вид регистра - регистр остатков).
Справочно, структура регистра:
Измерения:
Номенклатура - СправочникСсылка.Номенклатура
Качество - ПеречислениеСсылка.Качество
Ресурсы:
Количество - Число 15.3
Вместо эпилога: Уважаемые читатели, в общем статья была написана на коленке (писал сразу из головы (даже не в конструкторе/консоли запросов) , не спрашивайте почему так получилось - не скажу!) за полчаса..., в начале февраля выйдет переработанная и несколько расширенная статья (извините, но год закончился - пошла отчётностью, нововведения в законодательстве,.... времени не хватает совсем), если у кого-то есть пожелания увидеть что-то конкретное - пишите в коменты, постараюсь всё учесть. Обязательно напишу про простейшие приёмы и принципы оптимизации в запросах. Новая статья будет так-же написана максимально простым языком новичка для новичков, но надеюсь будет более продумана и не вызовет столько нареканий...
Всех с Крещением Господним!
И успехов всем нам в нашем нелёгком труде!
19.01.2011.