Упорядочивание результатов запроса. Маленькие хитрости больших запросов Использование консоли запросов

/
Реализация обработки данных

Упорядочивание результатов запроса

1.1. Если алгоритм обработки результатов запроса зависит от порядка записей в запросе или если результат обработки запроса в той или иной форме представляется пользователю , то в тексте запроса следует использовать предложение УПОРЯДОЧИТЬ ПО . В отсутствие выражения УПОРЯДОЧИТЬ ПО невозможно сделать никаких предположений о том, в каком порядке будут представлены записи в результатах запроса.

Типичные примеры проблем, которые могут возникать:

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

Вероятность возникновения разных результатов при выполнении одинаковых действий повышается

  • при переносе информационной базы на другую СУБД
  • при смене версии СУБД
  • при изменении параметров СУБД

* Примечание: упорядочивание результатов запросов, по которым формируются движения, оправдано только в том случае, если упорядочивание является частью алгоритма формирования движений (например, списание остатков партий товаров по FIFO). В остальных случаях упорядочивать записи не следует, так как дополнительное упорядочивание будет создавать избыточную нагрузку на СУБД.

1.2. Если результаты запроса должны тем или иным образом отображаться пользователю, то

  • упорядочивать результаты таких запросов необходимо по полям примитивных типов;
  • упорядочивание по полям ссылочных типов нужно заменять на упорядочивание по строковым представлениям этих полей.

В противном случае порядок следования строк будет выглядеть для пользователя случайным (необъяснимым).

См. также: Сортировка строк таблиц значений

1.3. Отсутствие предложения УПОРЯДОЧИТЬ ПО оправдано только в тех случаях, когда

  • алгоритм обработки результатов запроса не рассчитывает на определенный порядок записей
  • результат обработки выполненного запроса не показывается пользователю
  • результат запроса - заведомо одна запись

Совместное использование с конструкцией РАЗЛИЧНЫЕ

2. Если в запросе используется конструкция РАЗЛИЧНЫЕ , упорядочивание следует выполнять только по полям, включенным в выборку (в секции ВЫБРАТЬ ).

Данное требование связано со следующей особенностью выполнения запросов: в поля выборки неявно включаются поля упорядочивания, что в свою очередь может привести к появлению в результате запроса нескольких строк с одинаковыми значениями полей выборки.

Ограничения на использование конструкции АВТОУПОРЯДОЧИВАНИЕ

3. Использование конструкции ПЕРВЫЕ совместно с конструкцией АВТОУПОРЯДОЧИВАНИЕ запрещено.

В остальных случаях конструкцию АВТОУПОРЯДОЧИВАНИЕ также не рекомендуется использовать, так как разработчик не контролирует, какие именно поля будут использованы для упорядочивания. Применение такой конструкции оправдано только в тех случаях, когда получаемый порядок записей не важен, но при этом он должен быть одинаковым в не зависимости от применяемой СУБД.

Запросы предназначены для извлечения и обработки информации из базы данных для предоставления пользователю в требуемом виде. Под обработкой здесь подразумевается группировка полей, сортировка строк, расчет итогов и т.д. Изменять данные с помощью запросов в 1С нельзя!

Запрос выполняется в соответствии с заданными инструкциями — текстом запроса . Текст запроса составляется в соответствии с синтаксисом и правилами языка запросов . Язык запросов 1С:Предприятие 8 основан на базе стандартного SQL , но имеет некоторые отличия и расширения.

Схема работы с запросом

Общая схема работы с запросом состоит из нескольких последовательных этапов:

  1. Создание объекта Запрос и установка текста запроса;
  2. Установка параметров запроса;
  3. Выполнение запроса и получение результата;
  4. Обход результата запроса и обработка полученных данных.

1. Объект Запрос имеет свойство Текст , которому необходимо присвоить текст запроса.

// Вариант 1
Запрос = Новый Запрос;
Запрос. Текст =
«ВЫБРАТЬ
| КурсыВалют.Период,
| КурсыВалют.Валюта,
| КурсыВалют.Курс
|ИЗ

|ГДЕ
;

// Вариант 2
Запрос = Новый Запрос («ВЫБРАТЬ
| КурсыВалют.Период,
| КурсыВалют.Валюта,
| КурсыВалют.Курс
|ИЗ
| РегистрСведений.КурсыВалют КАК КурсыВалют
|ГДЕ
| КурсыВалют.Валюта = &Валюта» );

2. Установка значений параметров осуществляется методом УстановитьПараметр(< Имя>, < Значение>) . Параметры в тексте запроса обозначаются символом «& » и обычно используются в условиях отбора (секция ГДЕ) и в параметрах виртуальных таблиц.

Запрос);

3. После присвоения текста и установки параметров запрос необходимо выполнить и получить результат выполнения. Выполнение производится методом Выполнить () , который возвращает объект РезультатЗапроса . Из результата запроса можно:

  • получить выборку с помощью метода Выбрать(< ТипОбхода>, < Группировки>, < ГруппировкиДляЗначенийГруппировок>) ;
  • выгрузить значения в таблицу значений или дерево значений с помощью метода Выгрузить(< ТипОбхода>) .

// Получение выборки

Выборка = РезультатЗапроса. Выбрать ();

// Получение таблицы значений
РезультатЗапроса = Запрос. Выполнить();
Таблица = РезультатЗапроса. Выгрузить ();

4. Обойти выборку результата запроса можно с помощью цикла:

Пока Выборка .Следующий () Цикл
Сообщить (Выборка .Курс );
КонецЦикла;

Полный пример работы с запросом может выглядеть так:

// Этап 1. Создание запроса и установка текста запроса
Запрос = Новый Запрос;
Запрос. Текст =
«ВЫБРАТЬ
| КурсыВалют.Период,
| КурсыВалют.Валюта,
| КурсыВалют.Курс
|ИЗ
| РегистрСведений.КурсыВалют КАК КурсыВалют
|ГДЕ
| КурсыВалют.Валюта = &Валюта» ;

// Этап 2. Установка параметров
Запрос. УстановитьПараметр(«Валюта» , ВыбраннаяВалюта );

// Этап 3. Выполнение запроса и получение выборки
РезультатЗапроса = Запрос. Выполнить();
Выборка = РезультатЗапроса. Выбрать ();

// Обход выборки
Пока Выборка .Следующий () Цикл
Сообщить (Выборка .Курс );
КонецЦикла;

Состав текста запроса

Текст запроса состоит из нескольких секций:

  1. Описание запроса — перечень выбираемых полей и источников данных;
  2. Объединение запросов — выражения «ОБЪЕДИНИТЬ» и «ОБЪЕДИНИТЬ ВСЕ»;
  3. Упорядочивание результатов — выражение «УПОРЯДОЧИТЬ ПО …»;
  4. Автоупорядочивание — выражение «АВТОУПОРЯДОЧИВАНИЕ»;
  5. Описание итогов — выражение «ИТОГИ … ПО …».

Обязательной является только первая секция.

Временные таблицы и пакетные запросы

Язык запросов 1С поддерживает использование временных таблиц — таблиц, полученных в результате выполнения запроса и сохраненных на временной основе.

Часто можно столкнуться с ситуацией, когда в качестве источника запроса нужно использовать не таблицы базы данных, а результат выполнения другого запроса. Эту задачу можно решить с помощью вложенных запросов или временных таблиц . Применение временных таблиц позволяет упростить текст сложного запроса, разделив его на составные части, а также, в некоторых случаях, ускорить выполнение запроса и уменьшить количество блокировок. Для работы с временными таблицами используется объект МенеджерВременныхТаблиц . Создание временной таблицы производится при помощи ключевого слова ПОМЕСТИТЬ, за которым следует наименование временной таблицы.

МенеджерВТ = Новый МенеджерВременныхТаблиц;
Запрос = Новый Запрос;
Запрос. МенеджерВременныхТаблиц = МенеджерВТ;

Запрос. Текст =
«ВЫБРАТЬ
| Валюты.Код,
| Валюты.Наименование
|ПОМЕСТИТЬ ВТВалюты
|ИЗ
| Справочник.Валюты КАК Валюты» ;

РезультатЗапроса = Запрос. Выполнить ();

Для использования временной таблицы ВТВалюты в других запросах необходимо этим запросам присвоить общий менеджер временных таблиц — МенеджерВТ.

Пакетный запрос — это запрос, в котором содержится несколько запросов, разделенных символом «;». При выполнении пакетного запроса все входящие в него запросы выполняются последовательно, причем результаты всех временных таблиц доступны всем последующим запросам. Явное присвоение менеджера временных таблиц пакетным запросам не обязательно. Если менеджер временных таблиц не присвоен, то все временные таблицы удалятся сразу после выполнения запроса.

Для пакетных запросов доступен метод ВыполнитьПакет () , который выполняет все запросы и возвращает массив результатов. Временные таблицы в пакетном запросе будут представлены таблицей с одной строкой и одной колонкой «Количество», в которой хранится количество записей. Для отладки пакетных запросов можно использовать метод ВыполнитьПакетСПромежуточнымиДанными () : он возвращает реальное содержимое временных таблиц, а не количество записей.

// Пример работы с пакетным запросом
Запрос = Новый Запрос;
Запрос. Текст =
«ВЫБРАТЬ
| Валюты.Наименование
|ИЗ
| Справочник.Валюты КАК Валюты
|;
|ВЫБРАТЬ
| Номенклатура.Наименование
|ИЗ
| Справочник.Номенклатура КАК Номенклатура» ;

РезультатПакета = Запрос. ВыполнитьПакет();

ТЗВалюты = РезультатПакета[ 0 ]. Выгрузить();
ТЗНоменклатура = РезультатПакета[ 1 ]. Выгрузить();

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

Запрос. УстановитьПараметр(«Производитель» , Производитель);

РезультатЗапроса = Запрос. Выполнить();
Выборка = РезультатЗапроса. Выбрать ();

Пока Выборка .Следующий () Цикл

КонецЦикла;

Виртуальные таблицы

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

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

  • Для регистров сведений:
    • СрезПервых(<Период>, <Условие>) — наиболее ранние записи на указанную дату;
    • СрезПоследних(<Период>, <Условие>) — наиболее поздние записи на указанную дату;
  • Для регистров накопления:
    • Остатки(<Период>, <Условие>) — остатки на указанную дату;
    • Обороты(<НачалоПериода>, <КонецПериода>, <Периодичность>, <Условие>) — обороты за период;
    • ОстаткиИОбороты(<НачалоПериода>, <КонецПериода>, <Периодичность>, <МетодДополненияПериодов>, <Условие>) — остатки и обороты за период;
  • Для регистров бухгалтерии:
    • Остатки(<Период>, <УсловиеСчета>, <Субконто>, <Условие>) — остатки на указанную дату в разрезе счета, измерений и субконто;
    • Обороты(<НачалоПериода>, <КонецПериода>, <Периодичность>, <УсловиеСчета>, <Субконто>, <Условие>, <УсловиеКорСчета>, <КорСубконто>) — обороты за период в разрезе счета, измерений, кор. счета, субконто, кор. субконто;
    • ОстатковИОборотов(<НачалоПериода>, <КонецПериода>, <Периодичность>, <МетодДополненияПериодов>, <УсловиеСчета>, <Субконто>, <Условие>) — остатки и оборотов в разрезе счета, измерений и субконто;
    • ОборотыДтКт(<НачалоПериода>, <КонецПериода>, <Периодичность>, <УсловиеСчетаДт>, <СубконтоДт>, <УсловиеСчетаКт>, <СубконтоКт>, <Условие>) — обороты за период в разрезе счета Дт, счета Кт, Субконто Дт, Субконто Кт;
    • ДвиженияССубконто(<НачалоПериода>, <КонецПериода>, <Условие>, <Порядок>, <Первые>) — движения вместе со значениями субконто;
  • Для регистров расчета:
    • База(<ИзмеренияОсновногоРегистра>, <ИзмеренияБазовогоРегистра>, <Разрезы>, <Условие>) — базовые данные регистра расчета;
    • ДанныеГрафика(<Условие>) — данные графика;
    • ФактическийПериодДействия(<Условие>) — фактический период действия.

При работе с виртуальными таблицами следует накладывать отборы в параметрах виртуальных таблиц, а не в условии ГДЕ. От этого сильно зависит время выполнения запроса.

Конструктор запроса

Для ускорения ввода текстов запросов платформа имеет специальные инструменты: Конструктор запроса и Конструктор запроса с обработкой результата . Для вызова конструкторов необходимо щелкнуть правой кнопкой мыши и выбрать требуемый пункт:

Также конструкторы можно вызвать из главного меню Текст .

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

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

Объект СхемаЗапроса

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

  • УстановитьТекстЗапроса(< Текст>) — заполняет свойство ПакетЗапросов на основании переданного текста запроса;
  • ПолучитьТекстЗапроса () — возвращает сформированный на основании свойства ПакетЗапросов текст запроса;
  • НайтиПараметры () — возвращает параметры запроса.

Рассмотрим пример работы с объектом СхемаЗапроса. Для программного формирования текста запроса

УПОРЯДОЧИТЬ ПО
Валюты.Код

Код на встроенном языке может выглядеть так:

СхемаЗапроса = Новый СхемаЗапроса;
Пакет1 = СхемаЗапроса. ПакетЗапросов[ 0 ];
Оператор1 = Пакет1. Операторы[ 0 ];
// добавление источника
ТаблицаРегистра = Оператор1. Источники. Добавить(«Справочник.Валюты» , «Валюты» );
// добавление полей
ПолеСсылка = Оператор1. ВыбираемыеПоля. Добавить(«Валюты.Ссылка» , 0 );
ПолеКод = Оператор1. ВыбираемыеПоля. Добавить(«Валюты.Код» , 1 );
// указание псевдонимов полей
Пакет1. Колонки[ 0 ]. Псевдоним = «Валюта» ;
Пакет1. Колонки[ 1 ]. Псевдоним = «Код» ;
// добавление условия
Оператор1. Отбор. Добавить(«НЕ ПометкаУдаления» );
// добавление упорядочивания
Пакет1. Порядок. Добавить(ПолеКод);
ТекстЗапроса = СхемаЗапроса. ПолучитьТекстЗапроса ();

Сравнительно с предыдущей публикацией текста много, но по-другому совсем никак.

1.Полная форма использования оператора В.

Помимо формы, указанной в предыдущей публикации:

Поле В (&СписокЗначений),

Также в запросах языка 1С допустимы следующие формы использования этого оператора:

1.Поле В (&Массив)

2.Поле В (&Значение1,....&ЗначениеN),

3.Поле В (Выбрать …..) или для нескольких полей:

(Поле1, Поле2) В (Выбрать Т.Поле5, Т.Поле6 Из Таблица Т) , где Т - таблица (физическая, виртуальная или временная)

4.Поле В (&ТаблицаЗначений) или для нескольких полей:

(Поле1, Поле2) В (&ТаблицаЗначений)

Вариант записи №3 называют подзапросом.

У варианта №4 есть особенность: количество полей в Таблице значений должно точно совпадать с количеством полей, по которым производится проверка. Кроме того следует учесть что при сравнении по нескольким полям условие будет принимать значение Истина только при совпадении по всем полям одновременно.

2.Оператор В Иерархии.

Этот оператор может быть использован только для иерархических справочников (и других иерархических объектов, например План Счетов, План Видов Характеристик). По сути этот оператор очень схож с оператором В, но имеет совсем другой смысл: оператор производит проверку, что элемент справочника принадлежит указанной группе (или группам вложенным в указанную группу).

Пример использования: отбираем в запросе все элементы справочника номенклатура, которые находятся в группе товаров «Мебель» (для простоты элемент справочника «Номенклатура» Мебель - предопределённый).

Запрос.Текст = "ВЫБРАТЬ Номенклатура.Ссылка ИЗ Справочник.Номенклатура КАК Номенклатура

Запрос. УстановитьПараметр(" Группа1", Справочники. Номенклатура. Мебель);

Примечание1: если в качестве аргумента оператора В Иерархии указать пустой элемент - будут отобраны все элементы справочника (т.е. оператор в Иерархии будет возвращать значение Истина для любого элемента справочника, т.к. у элементов и групп самого верхнего уровня значение реквизита Родитель пустое), например: Запрос. УстановитьПараметр(" Группа1", Справочники. Номенклатура. ПустаяСсылка());

Примечание2: оператор В Иерархии очень мощный и позволяет проверить принадлежность группе для элементов справочника неограниченного уровня вложенности в рамках одного запроса (что невозможно сделать другими способами), но скорость работы этого оператора не сильно велика, что особенно заметно на больших справочниках.

3.Использование конструктора запроса.

В среде программистов 1С не редко возникают споры о использовании конструктора запросов или отказе от использования конструктора и написании запроса вручную. Тем не менее, по мнению большинства программистов, пользоваться конструктором нужно, но иногда после этого полученный запрос «допиливают руками». Для вызова конструктора запросов в любом модуле нужно кликнут по правой кнопке манипулятора мышь и из выпавшего меню выбрать или «Конструктор запроса» или «Конструктор запроса с обработкой результата».

Основные преимущества использования конструктора запросов:

1.Видимость всех доступных объектов конфигурации для построения запроса (а также всех временных таблиц запроса и т.п.).

2.Точное указание имён полей и реквизитов (т.к. они не набираются вручную а выбираются из списка).

3.Упрощенное отображение взаимосвязей между объектами запроса и условий.

4.Относительно изолированная работа над каждой частью запроса (каждым запросом в пакетном запросе или отдельном запросе при объединении запросов).

5.Абсолютно достоверные данные по «существующим» в данной конфигурации Виртуальным таблицам.

4.Работа с датами в запросах (дата, момент времени, граница)

В средствах разработки 1С, начиная с версии 8.0, тип данных Дата стал составным из Даты и Времени . И всё-бы было хорошо, но и тут есть свои особенности.

1 Проблемма. Время создания документов можно определить только с точностью до секунды, т.е.если мы дважды с небольшой паузой выполним следующий код:

Док

Док

Док = Документы. Приход. СоздатьДокумент(); Док. Дата = ТекущаяДата(); Док.Записать();

Док = Документы. Расход. СоздатьДокумент(); Док. Дата = ТекущаяДата(); Док.Записать();

А потом выполнить следующий запрос:

ОБЪЕДИНИТЬ ВСЕ

УПОРЯДОЧИТЬ ПО Дата

То получим странный результат:

Документы не упорядочены даже по порядку их создания! Если заменим реквизит документа Дата на реквизит МоментВремени в запросе получим уже более лучший результат:

В пределах 1 секунды идут сначала документы «Приход» этой секунды, а далее документы «Расход» этой секунды, причём номера документов идут строго в порядке возрастания (в нашем случае в виду автонумерации документов это означает что в порядке создания). Осталось решить небольшую проблему - упорядочить внутри секунды документы в реальном порядке их создания а не только для каждого вида документа - если заблаговременно не было задачи решения этой проблемы - она не разрешима в принципе.

Примечание: МоментВремени содержит дату, время и ссылку на объект базы данных. А т.к. ссылка содержит код типа объекта и уникальный номер объекта - то сортировка в пределах секунды по МоментуВремени в качестве результата выдаст группы разнотипных объектов внутри групп упорядоченных, но между собой не «перемешанных».

Как решить эту задачу:

1вариант: если номера самих документов не принципиальны - можно создать нумератор документов и тогда номер документа будет ответствовать его порядковому номеру при создании. Это решение очень плохо в виду отказа от сквозной нумерации документов.

2 вариант: ввести дополнительное идентификационное поле и перед сохранением документа с незаполненным значением этого поля получать значение этого поля для этого документа из любого сеансанезависимого источника, которым может быть и специальная запись непериодического Регистра Сведений и значение записное во внешний текстовый или другой файл или специально для этого написанный Com-сервис и т.п. и писать полученное значение в это поле, а сохраненное значение увеличить на единичку.

2 Проблема . Выбор времени для выполнения запроса получения остатков. При выполнении многих запросов нужно указывать конец периода выборки (т.е. момент на который получаются остатки). Казалось-бы вполне правильным было так:

Запрос . УстановитьПараметр(" КонецПериода " , КонецМесяца(ТекущаяДата()));

Но на самом деле запрос получения остатков будет выполнен по состоянию на начало указанной даты(которая есть дата+время). Если учесть, что КонецМесяца(Дата(2012, 10, 29)) = 31.10.0012 23:59:59

То получается, что у нас выпадают обороты формируемые движениями (документами) за последнюю секунду периода и мы получим остатки за секунду до конца месяца а не по состоянию на конец месяца! Особенно часто эта особенность приводит к ошибке получения остатков при импорте нечальных остатков (когда в последную секунду может поместиться огромное количество документов) и в организациях работающих в режиме 7*24.

Как решить эту проблему:

1 вариант: прибавить к концу периода 1 секунду:

Запрос . УстановитьПараметр(" КонецПериода " , КонецМесяца(ТекущаяДата())+1);

2 вариант: воспользоваться специально созданным для этого объектом Граница:

ГраницаПериода = Новый Граница(КонецМесяца(ТекущаяДата())+ 1, ВидГраницы. Исключая);

Запрос. УстановитьПараметр("КонецПериода" , ГраницаПериода);

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

ГраницаПериода = Новый Граница(Документ. МоментВремени, ВидГраницы. Исключая);

или если движения и этого документа должны попасть:

ГраницаПериода = Новый Граница(Документ. МоментВремени, ВидГраницы. Включая);

Примечание 2: Как справедливо заметили в комментариях ещё 1 плюс работы с типом данных Граница - не надо задумываться что выбираешь остатки или обороты и нет необходимости передавать в сложный запрос в котором выбираются и остатки и обороты 2 параметра описывающих момент на который проиводится выборка (один для оборотов, второй для остатков).

5.Выборка по группировкам, итоги.

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

Инструменты

Напильник

То обычная выборка запроса вида:

Выборка = Запрос. Выполнить(). Выбрать();

Выдаст список элементов и групп вообще говоря в произвольном порядке (если в запросе не сделано упорядочивание), но часто нужно выбирать результат с учётом иерархического подчинения, то эта задача выполняется небольшой модификацией запроса и чуть более сложным кодом выборки:

Запрос = Новый Запрос;

Запрос. Текст = "ВЫБРАТЬ Номенклатура.Ссылка КАК Номенклатура ИЗ Справочник.Номенклатура КАК Номенклатура

ИТОГИ ПО Номенклатура ИЕРАРХИЯ";

Выборка = Запрос.Выполнить(). Выбрать(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией, "Номенклатура" );

Сообщить("Элемент=" + ВыборкаДетали. Номенклатура);

КонецЦикла;

КонецЦикла;

Кроме того есть платформа позволяет при выполнении выборки производить расчёт итогов на каждом уровне, пусть для простоты запроса итоги берём из справочника (а не из регистров накопления) :

Запрос = Новый Запрос;

Запрос. Текст = "ВЫБРАТЬ Номенклатура.Ссылка КАК Номенклатура, Номенклатура.Продано КАК Продано

ИЗ Справочник.Номенклатура КАК Номенклатура

ИТОГИ СУММА(Продано)

ПО Номенклатура ИЕРАРХИЯ";

Выборка = Запрос. Выполнить(). Выбрать(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией, "Номенклатура" );

Пока Выборка. Следующий() Цикл

Сообщить("Группа=" + Выборка. Номенклатура+ " Продано=" + Выборка. Продано);

ВыборкаДетали = Выборка.Выбрать(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией, "Номенклатура" );

Пока ВыборкаДетали. Следующий() Цикл

Сообщить("Элемент=" + ВыборкаДетали. Номенклатура+ " Продано=" + ВыборкаДетали. Продано);

КонецЦикла;

КонецЦикла;

Примечание1: есть ещё один вариант обход «ПоГруппировкам», отличается от иерархического обхода тем, что элементы выборки с иерархическими итогами будут в нем как детальные записи а не узловые.

Примечание2: для обхода справочника с более сложной структурой (количеством уровней>2) можно воспользоваться рекурсией, например вот так:

……………………..

Выборка = Запрос.Выполнить(). Выбрать(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией);
ВыбратьРекурсивно(Выборка);

………….
КонецПроцедуры

Процедура ВыбратьРекурсивно(Выборка)

Пока Выборка.Следующий() Цикл

Сообщить(Выборка. Номенклатура+ " колво=" + Выборка. Продано);

// Попытка получить дочерние записи

ВыбратьРекурсивно(Выборка. Выбрать(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией);
КонецЦикла;
КонецПроцедуры

Примечание3: ещё одно применение иерархической выборки - выгрузка результатов запроса в объект типа Дерево Значений, например так:

ЗначениеВРеквизитФормы(Результат. Выгрузить(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией, "Дерево" );

Дерево = Результат. Выгрузить(ОбходРезультатаЗапроса. ПоГруппировкамСИерархией);

6.Временные таблицы, пакетные запросы .

Ещё одной очень мощной возможностью языка запросов 1С является работа с временными таблицами. По сути, мы результат запроса помещаем во временную таблицу, с которой далее можем работать как с обычной таблицей. Сам запрос становится составным из нескольких запросов, которые выполняются строго последовательно, один (последний) запрос пакета выполняет выборку данных - такой составной запрос называют пакетным запросом. Каждая временная таблица имеет своё имя и т.о. в пакетном запросе может создаваться произвольное количество таблиц. Время жизни временной таблицы ограниченно временем выполнения запроса, как только запрос был выполнен - все временные таблицы уничтожаются, а память занятая хранением данных временных таблиц высвобождается.

Для того чтобы выполнить помещение данных во временную таблицу используется оператор ПОМЕСТИТЬ , который пишется в запросе между операторами ВЫБРАТЬ и ИЗ . Запросы внутри пакетного запроса отделяются друг от друга строками:

////////////////////////////////////////////////////////////

Пример небольшого пакетного запроса выбирающего последний документ продажи «Реализация» (у документа есть табличная часть «Товары», в которой перечислены реализованные товары) для каждой номенклатуры.

Схема пакетного запроса:

в 1 запросе получаем полный перечень продаваемой номенклатуры и максимальную дату продажи для каждой из номенклатур,

во 2 запросе отбираем для каждой номенклатуры из первого запроса документ реализации с датой равной для этой номенклатуры максимальной

ВЫБРАТЬ РелизацияТовары.Номенклатура, МАКСИМУМ(РеализацияТоваровТовары.Ссылка.Дата) КАК Дата

ПОМЕСТИТЬ Даты

ИЗ Документ.Реализация.Товары КАК РеализацияТовары

СГРУППИРОВАТЬ ПО РеализацияТовары.Номенклатура

////////////////////////////////////////////////////////////

ВЫБРАТЬ Даты.Номенклатура, Даты.Дата, МАКСИМУМ(Реализация.Ссылка) КАК Ссылка

ИЗ Даты КАК Даты

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Документ.Реализация КАК Реализация

ПО Даты.Дата = Реализация.Дата

СГРУППИРОВАТЬ ПО Реализация.Ссылка

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

7.Последовательность чисел, дат.

Задача: генерация числовой последовательности от 0 до 959 в запросе. При использовании пакетного запроса задача решается легко:

ВЫБРАТЬ Цифры.Поле1 КАК Цифра

ПОМЕСТИТЬ Цифры

ИЗ (ВЫБРАТЬ 1 КАК Поле1

ОБЪЕДИНИТЬ ВЫБРАТЬ 2

ОБЪЕДИНИТЬ ВЫБРАТЬ 3

ОБЪЕДИНИТЬ ВЫБРАТЬ 4

ОБЪЕДИНИТЬ ВЫБРАТЬ 5

ОБЪЕДИНИТЬ ВЫБРАТЬ 6

ОБЪЕДИНИТЬ ВЫБРАТЬ 7

ОБЪЕДИНИТЬ ВЫБРАТЬ 8

ОБЪЕДИНИТЬ ВЫБРАТЬ 9

ОБЪЕДИНИТЬ ВЫБРАТЬ 10) КАК Цифры

ВЫБРАТЬ (Цифры.Цифра- 1) + (Цифры1.Цифра - 1)* 10+ (Цифры2.Цифра - 1)* 100 КАК Число

ГДЕ (Цифры.Цифра- 1) + (Цифры1.Цифра - 1)* 10+ (Цифры2.Цифра - 1)* 100 <= 959

УПОРЯДОЧИТЬ ПО Число

Задача : генерация последовательности дат от Дата1 до Дата2 . Решается аналогично, можно как выполнить в 3 шага (первый и второй как в приведённом примере, но результат не выбрать а поместить во временную таблицу) или в 2 шага изменив второй запрос пакета на вот такой:

ВЫБРАТЬ ДОБАВИТЬКДАТЕ (&Дата1 , ДЕНЬ , (Цифры.Цифра- 1) + (Цифры1.Цифра - 1)* 10+ (Цифры2.Цифра - 1)* 100) КАК Дата

ИЗ Цифры КАК Цифры, Цифры КАК Цифры1, Цифры КАК Цифры2

ГДЕ ДОБАВИТЬКДАТЕ (&Дата1 , ДЕНЬ , (Цифры.Цифра- 1) + (Цифры1.Цифра - 1)* 10+ (Цифры2.Цифра - 1)* 100)

УПОРЯДОЧИТЬ ПО Дата

Примечание: естественно этот запрос будет правильно работать только если между датами Дата1 и Дата2 не более 999 дней.

8.Использование данных из таблицы значений в запросе.

Если в первом разделе (оператор В ) мы производим сравнение набора полей с данными из Таблицы значений, то иногда этого мало. Например, из стороннего источника передаются наборы данных, например такие: штрих-код и количество единиц проданной продукции. Можно конечно в запросе обойти переданный набор значений выполняя на каждой итерации цикла запрос, но это наихудший вариант решения этой задачи. Правильнее сделать так:

1.Создать типизированную Таблицу значений (т.е. у которой указан тип для каждого поля).

2.Заполнить Таблицу значений полученными данными о продажах.

3.Произвести поиск номенклатуры в запросе.

Пример кода для 1 и 3 этапа:

Создание типизированной Таблицы значений:

// Создание описателей типов для таблицы значений

КЧК = Новый КвалификаторыЧисла(14, 3);

КЧШК = Новый КвалификаторыЧисла(13, 0);

Массив = Новый Массив;

Массив. Добавить(Тип("Число" ));

ОписаниеТиповЧК = Новый ОписаниеТипов(Массив, КЧК);

Массив. Очистить();

Массив. Добавить(Тип(" Число"));

ОписаниеТиповЧШ = Новый ОписаниеТипов(Массив, КЧШК);

// Создание таблицы значений

ТаблицаЗначений = Новый ТаблицаЗначений;

// добавим в таблицу значений две колонки

ТаблицаЗначений. Колонки.Добавить("ШтрихКод" , ОписаниеТиповЧШ, "ШтрихКод" , 13); ТаблицаЗначений. Колонки. Добавить("Продано" , ОписаниеТиповЧК, "Продано" , 14);

Поиск Номенклатуры в запросе:

Запрос = Новый Запрос;

Запрос.Текст = "ВЫБРАТЬ ТЗ.ШтрихКод, ТЗ.Количество

ПОМЕСТИТЬ ТЗ

ИЗ &ТЗ КАК ТЗ

////////////////////////////////////////////////////////////////////////////////

ВЫБРАТЬ ТЗ.Количество КАК ОбъемПродаж, Номенклатура.Ссылка КАК Ссылка

ИЗ ТЗ КАК ТЗ

ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура

ПО ТЗ.ШтрихКод = Номенклатура.ШтрихКод";

Запрос. УстановитьПараметр("ТЗ" , ТаблицаЗначений);

Примечание: для работы с Таблицей Значений в запросе всегда необходимо сначала данные из Таблицы Значений поместить воВременную Таблицу, а уже потом можно работать с этими данными внутри пакетного запроса.

Язык запросов является одним из основополагающих механизмов 1С 8.3 для разработчиков. При помощи запросов можно быстро получить любые данные, хранящиеся в базе. Его синтаксис очень похож на SQL, но есть и отличия.

Основные достоинства языка запросов 1С 8.3 (8.2) перед SQL:

  • разыменование ссылочных полей (обращение черед одну или несколько точек к реквизитам объектов);
  • работа с итогами очень удобная;
  • возможность создавать виртуальные таблицы;
  • запрос можно писать как на английском, так и на русском языках;
  • возможность блокировать данные для исключения взаимных блокировок.

Недостатки языка запросов в 1С:

  • в отличие от SQL, в 1С запросы не позволяют изменять данные;
  • отсутствие хранимых процедур;
  • невозможность преобразования строки в число.

Рассмотрим наш мини учебник по основным конструкциям языка запросов 1С.

В связи с тем, что запросы в 1С позволяют лишь получать данные, любой запрос должен начинаться со слова «ВЫБРАТЬ». После этой команды указываются поля, данные из которых нужно получить. Если указать «*», то будут выбраны все доступные поля. Место, откуда будут выбираться данные (документы, регистры, справочники и прочее) указывается после слова «ИЗ».

В рассмотренном ниже примере выбираются наименования всей номенклатуры из справочника «Номенклатура». После слова «КАК» указываются псевдонимы (имена) для таблиц и полей.

ВЫБРАТЬ
Номенклатура.Наименование КАК НаименованиеНоменклатуры
ИЗ
Справочник.Номенклатура КАК Номенклатура

Рядом с командой «ВЫБРАТЬ» можно указать ключевые слова:

  • РАЗЛИЧНЫЕ . Запрос будет отбирать только отличающиеся хотя бы по одному полю строки (без дублей).
  • ПЕРВЫЕ n , где n – количество строк с начала результата, которые необходимо отобрать. Чаще всего такая конструкция используется совместно с сортировкой (УПОРЯДОЧИТЬ ПО). Например, когда нужно отобрать определенное количество последних по дате документов.
  • РАЗРЕШЕННЫЕ . Данная конструкция позволяет выбирать из базы только те записи, которые доступны текущему пользователю. Баз использования этого ключевого слова пользователю будет выведено сообщение об ошибке при попытке обращения запроса к тем записям, доступа к которым у него нет.

Эти ключевые слова могут использоваться как все вместе, так и по отдельности.

ДЛЯ ИЗМЕНЕНИЯ

Это предложение блокирует данные для исключения взаимных конфликтов. Заблокированные данные не будут считываться из другого соединения до окончания транзакции. В данном предложении можно указывать конкретные таблицы, которые нужно заблокировать. В противном случае будут заблокированы все. Конструкция актуальна лишь для режима автоматических блокировок.

Чаще всего предложение «ДЛЯ ИЗМЕНЕНИЯ» используется при получении остатков. Ведь при одновременной работе нескольких пользователей в программе, пока один получает остатки, другой может их изменить. В таком случае полученный остаток будет уже не верен. Если же заблокировать данные этим предложением, то пока первый сотрудник не получит корректный остаток и не совершит с ним все необходимые манипуляции, второй сотрудник будет вынужден ждать.

ВЫБРАТЬ
Взаиморасчеты.Сотрудник,
Взаиморасчеты.СуммаВзаиморасчетовОстаток
ИЗ
РегистрНакопления.ВзаиморасчетыССотрудниками.Остатки КАК Взаиморасчеты
ДЛЯ ИЗМЕНЕНИЯ

ГДЕ (WHERE)

Конструкция необходима для наложения какого-либо отбора на выгружаемые данные. В некоторых случая получения данных из регистров разумнее прописывать условия отборов в параметрах виртуальных таблиц. При использовании «ГДЕ», сначала получаются все записи, и только потом применяется отбор, что значительно замедляет выполнение запроса.

Ниже приведен пример запроса получения контактных лиц с определенной должностью. Параметр отбора имеет формат: &ИмяПараметра (имя параметра произвольное).

ВЫБОР (CASE)

Конструкция позволяет указывать условия непосредственно в теле запроса.

В приведенном ниже примере «ДополнительноеПоле» будет содержать текст в зависимости от того проведен документ или нет:

ВЫБРАТЬ
ПоступлениеТиУ.Ссылка,
ВЫБОР
КОГДА ПоступлениеТиУ.Проведен
ТОГДА «Документ проведен!»
ИНАЧЕ «Документ не проведен…»
КОНЕЦ КАК ДополнительноеПоле
ИЗ
Документ.ПоступлениеТоваровУслуг КАК ПоступлениеТиУ

СОЕДИНЕНИЕ (JOIN)

Соединения связывают две таблицы по определенному условию связи.

ЛЕВОЕ/ПРАВОЕ СОЕДИНЕНИЕ

Суть ЛЕВОГО соединения заключается в том, что полностью берется первая указанная таблица и к ней по условию связи привязывается вторая. Если записей, соответствующих первой таблице во второй не нашлось, то в качестве их значений подставляется NULL. Проще говоря, главной является первая указанная таблица и к её данным уже подставляются данные второй таблицы (если они есть).

Например, необходимо получить номенклатурные позиции из документов «Поступление товаров и услуг» и цены из регистра сведений «Цены номенклатуры». В данном случае, если цена у какой-либо позиции не найдена, вместо нее подставиться NULL. Из документа все позиции будут выбраны вне зависимости от того, есть ли на них цена или нет.

ВЫБРАТЬ
ПоступлениеТиУ.Номенклатура,
Цены.Цена
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТиУ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ПО ПоступлениеТиУ.Номенклатура = Цены.Номенклатура

В ПРАВОМ все в точности да наоборот.

ПОЛНОЕ СОЕДИНЕНИЕ

Данный вид соединения отличается от предыдущих тем, что в результате будут возвращены все записи как первой таблицы, так и второй. Если по заданному условию связи в первой или второй таблице не найдено записей, вместо них будет возвращено значение NULL.

При использовании в предыдущем примере полного соединения будут выбраны все позиции номенклатуры из документа «Поступление товаров и услуг» и все последние цены из регистра «Цены номенклатуры». Значения не найденных записей, как в первой, так и во второй таблице будут равняться NULL.

ВНУТРЕННЕЕ СОЕДИНЕНИЕ

Отличием ВНУТРЕННЕГО соединения от ПОЛНОГО является то, что если хотя бы в одной из таблиц не найдена запись, то запрос не выведет ее вообще. В результате будут выбраны только те номенклатурные позиции из документа «Поступление товаров и услуг», для которых в регистре сведений «Цены номенклатуры» есть записи, если в предыдущем примере заменить «ПОЛНОЕ» на «ВНУТРЕННЕЕ».

СГРУППИРОВАТЬ ПО (GROUP BY)

Группировка в запросах 1С позволяет сворачивать строки таблицы (группировочные поля) по определенному общему признаку (группируемым полям). Группировочные поля могут выводиться только с применением агрегатных функций.

Результатом следующего запроса будет список видов номенклатуры с максимальными ценами по ним.

ВЫБРАТЬ
,
МАКСИМУМ(Цены.Цена) КАК Цена
ИЗ

СГРУППИРОВАТЬ ПО
Цены.Номенклатура.ВидНоменклатуры

ИТОГИ

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

Итоги можно подводить по всей таблице целиком (с использованием ключевого слова «ОБЩИЕ»), по нескольким полям, по полям с иерархической структурой (ключевые слова «ИЕРАРХИЯ», «ТОЛЬКО ИЕРАРХИЯ»). При подведении итогов не обязательно использовать агрегатные функции.

Рассмотрим пример, аналогичный примеру выше с использованием группировки. В данном случае результат запроса вернет не только сгруппированные поля, но и детальные записи.

ВЫБРАТЬ
Цены.Номенклатура.ВидНоменклатуры КАК ВидНоменклатуры,
Цены.Цена КАК Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
ИТОГИ
МАКСИМУМ(Цена)
ПО
ВидНоменклатуры

ИМЕЮЩИЕ (HAVING)

Данный оператор схож с оператором «ГДЕ», но используется только для агрегатных функций. Остальные поля, кроме используемых этим оператором, должны быть сгруппированы. Оператор «ГДЕ» не применим для агрегатных функций.

В рассмотренном ниже примере отбираются максимальные цены номенклатуры, если они превышают 1000, сгруппированные по виду номенклатуры.

ВЫБРАТЬ

МАКСИМУМ(Цены.Цена) КАК Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних КАК Цены
СГРУППИРОВАТЬ ПО
Цены.Номенклатура.ВидНоменклатуры
ИМЕЮЩИЕ
МАКСИМУМ(Цены.Цена) > 1000

УПОРЯДОЧИТЬ ПО

Оператор «УПОРЯДОЧИТЬ ПО» сортирует результат запроса. Для того, чтобы гарантированно выводить записи в постоянном порядке, используется АВТОУПОРЯДОЧИВАНИЕ. Примитивные типы сортируются по обычным правилам. Ссылочные типы сортируются по GUID.

Пример получения списка сотрудников, отсортированного по наименованию:

ВЫБРАТЬ
Сотрудники.Наименование КАК Наименование
ИЗ
Справочник.Сотрудники КАК Сотрудники
УПОРЯДОЧИТЬ ПО
Наименование
АВТОУПОРЯДОЧИВАНИЕ

Прочие конструкции языка запросов 1С

  • ОБЪЕДИНИТЬ – результаты двух запросов в один.
  • ОБЪЕДИНИТЬ ВСЕ – аналог ОБЪЕДИНИТЬ, но без группировки одинаковых строк.
  • ПУСТАЯ ТАБЛИЦА – иногда используется при объединении запросов для указания пустой вложенной таблицы.
  • ПОМЕСТИТЬ – создает временную таблицу для оптимизации сложных запросов 1С. Такие запросы называются пакетными.

Функции языка запросов

  • ПОДСТРОКА обрезает строку с определенной позиции на указанное количество символов.
  • ГОД…СЕКУНДА позволяют получить выбранное значение числового типа. Входным параметром является дата.
  • НАЧАЛОПЕРИОДА и КОНЕЦПЕРИОДА используются при работе с датами. В качестве дополнительного параметра указывается тип периода (ДЕНЬ, МЕСЯЦ, ГОД и т. п.).
  • ДОБАВИТЬКДАТЕ позволяет прибавить или отнять от даты указанное время определенного типа (СЕКУНДА, МИНУТА, ДЕНЬ и т. п.).
  • РАЗНОСТЬДАТ определяет разницу между двумя датами с указанием типа выходного значения (ДЕНЬ, ГОД, МЕСЯЦ и т. п.).
  • ЕСТЬNULL заменяет отсутствующее значение на указанное выражение.
  • ПРЕДСТАВЛЕНИЕ и ПРЕДСТАВЛЕНИЕССЫЛКИ получают строковое представление указанного поля. Применяются для любых значений и только ссылочных соответственно.
  • ТИП, ТИПЗНАЧЕНИЯ используются для определения типа входного параметра.
  • ССЫЛКА является логическим оператором сравнения для типа значения реквизита.
  • ВЫРАЗИТЬ используется для преобразования значения к нужному типу.
  • ДАТАВРЕМЯ получает значение типа «Дата» из числовых значений (Год, Месяц, День, Час, Минута, Секунда).
  • ЗНАЧЕНИЕ в запросе 1С используется для указания предопределенных значений — справочников, перечислений, планов видов характеристик. Пример использования: «Где ЮрФизЛицо = Значение(Перечисление.ЮрФизЛица.ФизЛицо) «.

Конструктор запросов

Для создания запросов с 1С есть очень удобный встроенный механизм – конструктор запросов. Он содержит следующие основные вкладки:

  • «Таблицы и поля» — содержит поля, которые необходимо выбрать и их источники.
  • «Связи» — описывает условий для конструкции СОЕДИНЕНИЕ.
  • «Группировка» — содержит описание конструкций группировок и суммируемых полей по ним.
  • «Условия» — отвечает за отборы данных в запросе.
  • «Дополнительно» — дополнительные параметры запроса, такие как ключевые слова команды «ВЫБРАТЬ» и пр.
  • «Объединения/Псевдонимы» — указываются возможности объединения таблиц и задаются псевдонимы (конструкция «КАК»).
  • «Порядок» — отвечает за сортировку результата запросов.
  • «Итоги» — аналогична вкладке «Группировка», но применяется для конструкции «ИТОГИ».

Текст самого запроса можно просмотреть, нажав в левом нижнем углу на кнопку «Запрос». В данной форме его можно откорректировать вручную или скопировать.


Консоль запросов

Для быстрого просмотра результата запроса в режиме «Предприятие», либо отладки сложных запросов используется . В ней пишется текст запроса, устанавливаются параметры, и показывается его результат.

Скачать консоль запросов можно на диске ИТС, либо по .

Внимание! Перед вами ознакомительная версия урока, материалы которого могут быть неполными.

Войдите на сайт как ученик

Войдите как ученик, чтобы получить доступ к материалам школы

Язык запросов 1С 8.3 для начинающих программистов: упорядочивание

Давайте напишем запрос, который получает из таблицы Справочник.Еда код и название еды:

ВЫБРАТЬ Код, Наименование ИЗ Справочник. Еда

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

С большой долей вероятности у вас получится следующий результат:

Возможно вы удивитесь, но при таком написании запроса никто не гарантирует нам именно такого порядка выдачи записей в таблице. В случае использования клиент-серверного режима работы на различных СУБД результат мог бы быть и такой:

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

Поэтому правилом хорошего тона при написании запросов считается упорядочивание результатов запроса даже тогда, когда нам этого не требуется явно.

Секция УПОРЯДОЧИТЬ ПО

Поля по которым требуется упорядочить запрос перечисляются в секции УПОРЯДОЧИТЬ ПО через запятую:

Следом за именем поля упорядочивания может идти одно из двух ключевых слов:

  • ВОЗР - упорядочивание по возрастанию.
  • УБЫВ - упорядочивание по убыванию.

Если не указывать ни одно из этих слов, считается, что сортировка идёт по возрастанию.

Вооружившись знаниями, давайте упорядочим результат нашего запроса по убыванию поля Код :

А теперь упорядочим следующую таблицу

так, чтобы сначала шла сортировка по полю Вкус по возрастанию, а затем (среди строчек с одинаковым значением поля Вкус ) шла сортировка по полю Цвет по убыванию:

ВЫБРАТЬ Вкус, Цвет ИЗ Справочник. Еда УПОРЯДОЧИТЬ ПО Вкус. Наименование ВОЗР, Цвет. Наименование УБЫВ

Отдельно обращаю ваше внимание на то, что мы указали сортировку не по самим полям Вкус и Цвет, а по их строковому реквизиту Наименование . Вы читаете ознакомительную версию урока, полноценные уроки находятся .

Это связано с тем, что сортировка возможна лишь по полям имеющим один из типов: Строка , Число , Дата .

А поля Вкус и Цвет являются ссылками на элементы справочников Вкус и Цвет , сортировать по которым не имеет смысла (в этом случае сортировка будет вестись по внутреннему идентификатору ссылки). Зато можно сделать сортировку по одному из реквизитов этих элементов. Наиболее подходящим в нашем случае будет строковый реквизит Наименование .

Возможность автоупорядочивания

Ключевое слово АВТОУПОРЯДОЧИВАНИЕ позволяет включить режим автоматического формирования полей для упорядочивания результатов запроса.

Мы сейчас познакомимся с этой возможностью подробно, но сразу хочется оговориться, что фирма "1С" в своих методических рекомендациях не советует использовать её без необходимости (о причинах этого мы поговорим ).

Итак, поехали.

Прежде всего, ключевое слово АВТОУПОРЯДОЧИВАНИЕ может быть расположено в запросе сразу за или вместо секции УПОРЯДОЧИТЬ ПО:

Автоупорядочивание работает по следующим принципам:

Случай #1

Если в запросе:

  • есть секция УПОРЯДОЧИТЬ ПО

Для таблиц справочников полями сортировки по умолчанию являются код и наименование, выбор из которых осуществляется в соответствии с настройками справочника в конфигураторе:

Для таблиц документов полем сортировки по умолчанию является дата документа.

Рассмотрим пример:

Так как поле сортировки ЛюбимыйЦвет имеет тип Справочник.Цвета Наименование

Случай #2

Если в запросе:

  • но есть секция ИТОГИ ПО (её мы будем проходить )

В этом случае результат запроса будет упорядочен по полям итогов (в той же последовательности).

Случай #3

Если в запросе:

  • отсутствует секция УПОРЯДОЧИТЬ ПО
  • отсутствует секция ИТОГИ ПО
  • но есть секция СГРУППИРОВАТЬ ПО (группировку мы проходили )

В этом случае результат запроса будет упорядочен по полям группировки (в той же последовательности).

Рассмотрим пример:

Так как поле группировки Город имеет тип Справочник.Города , в настройках которого основным представлением выбрано поле Наименование , то этот запрос эквивалентен:

Случай #4

Наконец, если в запросе:

  • отсутствует секция УПОРЯДОЧИТЬ ПО
  • отсутствует секция ИТОГИ ПО
  • отсутствует секция СГРУППИРОВАТЬ ПО

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

Рассмотрим пример:

Почему использование автоупорядочивания нежелательно

Автоупорядочивание подходит:

  • для универсальных запросов, когда разработчик не может предвидеть из каких таблиц будут запрашиваться данные
  • для случаев, когда получаемый порядок записей не важен, но при этом он должен быть одинаковым в независимости от применяемой СУБД

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

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

А завтра фирма "1С" (или другой разработчик) изменят настройки базы в конфигураторе так, что полем сортировки по умолчанию для справочника Еда станет, к примеру, поле Код . И, если мы использовали автоупорядочивание в запросе, то наш отчет сломается, ведь порядок сортировки уже будет другим. Вы читаете ознакомительную версию урока, полноценные уроки находятся .

Поэтому всегда старайтесь указывать конкретные поля и конкретный порядок сортировки по ним в секции УПОРЯДОЧИТЬ ПО , такой запрос уже не сломать просто так:

ВЫБРАТЬ Код, Наименование ИЗ Справочник. Еда УПОРЯДОЧИТЬ ПО Наименование ВОЗР

Пройдите тест

Начать тест

1. По умолчанию результаты запроса упорядочиваются

2. Результаты запроса можно упорядочивать по

3. "УПОРЯДОЧИТЬ ПО ИМЯ_ПОЛЯ" упорядочивает по

4. Чтобы упорядочить по возрастанию в секции УПОРЯДОЧИТЬ ПО необходимо указать имя поля и ключевое слово

5. Чтобы упорядочить по убыванию в секции УПОРЯДОЧИТЬ ПО необходимо указать имя поля и ключевое слово

6. Автоупорядочивание в запросах возможно


Top