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

Язык запросов 1С — одно из основных отличий между версиями 7.7 и 8. Одним из важнейших пунктов в изучении 1С-программирования является язык запросов. В 1С 8.3 запросы — самый мощный и эффективный инструмент получения данных. Язык запросов позволяет в удобном виде получать информацию из базы данных.

Сам синтаксис очень сильно напоминает классический T-SQL, за исключением того, что в 1С с помощью языка запросов можно только получать данные, используя конструкцию Выбрать(select). Язык поддерживает и более сложные конструкции, например, (запрос в запросе). Запросы в 1С 8 можно составлять как на кириллице, так и на латинице.

В статье я постараюсь рассказать про основные ключевые слова в языке запросов 1С:

  • выбрать
  • разрешенные
  • различные
  • выразить
  • первые
  • для изменения
  • значение
  • тип значения (и оператор ССЫЛКА)
  • выбор
  • сгруппировать по
  • имеющие
  • ЕСТЬNULL
  • Есть NULL
  • соединения — правые, левые, внутренние, полные .

А так же небольшие хитрости языка 1С, применяя которые вы сможете оптимально построить текст запроса.

Для отладки запросов в системе 1С 8.2 предусмотрен специальный инструмент — консоль запросов. Увидеть описание и скачать его можно по ссылке — .

Рассмотрим самые важные и интересные операторы языка запросов 1С.

ВЫБРАТЬ (SELECT)

В языке запросов 1С предприятия 8 любой запрос начинается с ключевого слова ВЫБРАТЬ . В языке 1С нет конструкций UPDATE, DELETE, CREATE TABLE, INSERT, эти манипуляции производятся в объектной технике. Предназначение его — только чтение данных.

Например:

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

Запрос вернёт таблицу с наименованиями номенклатуры.

Рядом с конструкцией ВЫБРАТЬ можно встретить ключевые слова ДЛЯ ИЗМЕНЕНИЯ , РАЗРЕШЕННЫЕ , РАЗЛИЧНЫЕ , ПЕРВЫЕ

РАЗРЕШЕННЫЕ — выбирает только записи из таблицы, на которые есть права у текущего пользователя.

РАЗЛИЧНЫЕ — означает, что в результат не попадет дублирующих строк.

ВЫБОР (CASE)

Очень часто данная конструкция недооценивается программистами. Пример её использования:

ТекущийСправочник.Наименование,

КОГДА ТекущийСправочник.Услуга ТОГДА

«Услуга»

КОНЕЦ КАК ВидНоменклатуры

Справочник.Номенклатура КАК ТекущийСправочник

Пример возвратит в поле «ВидНоменклатуры» текстовое значение — «Товар» или «Услуга».

ГДЕ (WHERE)

Конструкция языка запросов 1C, позволяющая наложить отбор на получаемые данные. Учтите, что от сервера система получает все данные, а только потом они отбираются по данному параметру.

ВЫБРАТЬ
Справочник.Наименование
ИЗ
ТекущийСправочник.Номенклатура КАК ТекущийСправочник
ГДЕ ТекущийСправочник.Услуга = ИСТИНА

В примере мы отбираем записи, у которых значение реквизита «Услуга» установлено в положение «Истина». В данном примере можно было бы обойтись и таким условием:

«ГДЕ Услуга»

По сути, мы отбираем строки, у которых выражение после ключевого слова равно «Истина».

В выражениях можно использовать прямые условия:

ГДЕ Код = «005215»

С помощью оператора «ЗНАЧЕНИЕ()» в условиях использовать обращение к предопределенным элементам и перечислениям в запросе 1С:

ГДЕ ТипНоменклатуры= Значение(Перечисление.ТипыНоменклатуры.Товар)

Значения времени могут указываться следующим образом:

ГДЕ ДатаПоступления > ДАТАВРЕМЯ(2012,01,01):

Чаще всего условия указываются в виде параметров, передаваемых в запрос:

Получите 267 видеоуроков по 1С бесплатно:

ГДЕ НоменклатурнаяГруппа= &НоменклатурнаяГруппа

Условие можно наложить на тип реквизита, если он составного типа:

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

ГДЕ РегистрНакопления.Регистратор В (&СписокДокументовДляОтбора)

Условие может быть и сложное, состоящее из нескольких условий:

ГДЕ ДатаПоступления > ДАТАВРЕМЯ(2012,01,01) И НоменклатурнаяГруппа= &НоменклатурнаяГруппа И НЕ Услуга

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

Конструкция языка запросов 1С 8.2, используемая для группировки результата.

Например:

ВЫБРАТЬ
ПоступлениеТоваровУслугTовары.Товар,
СУММА(ПоступлениеТоваровУслугTовары.Количество) КАК Количество,
СУММА(ПоступлениеТоваровУслугTовары.Сумма) КАК Сумма
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугTовары

СГРУППИРОВАТЬ ПО
ПоступлениеТоваровУслугTовары.Товар

Данный запрос просуммирует все поступления по сумме и количеству в разрезе номенклатуры.

Помимо ключевого слова СУММА можно использовать другие агрегатные функции: КОЛИЧЕСТВО , КОЛИЧЕСТВО РАЗНЫХ , МАКСИМУМ , МИНИМУМ , СРЕДНЕЕ .

ИМЕЮЩИЕ (HAVING)

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

Пример использования ИМЕЮЩИЕ в запросе 1С:

ВЫБРАТЬ
ПоступлениеТоваровУслугТовары.Товар,
СУММА(ПоступлениеТоваровУслугТовары.Количество) КАК Количество,
СУММА(ПоступлениеТоваровУслугТовары.Сумма) КАК Сумма
ИЗ
Документ.ПоступлениеТоваровУслуг.Товары КАК ПоступлениеТоваровУслугТовары

СГРУППИРОВАТЬ ПО
ПоступлениеТоваровУслугТовары.товар

СУММА(ПоступлениеТоваровУслугТовары.Количество) > 5

Так мы отберем количество товаров, которых поступило более 5 штук.

ЗНАЧЕНИЕ()

Например:

ГДЕ Банк = Значение(Справочник.Банки.ПустаяСсылка)

ГДЕ ВидНоменклатуры = Значение(Справочник.ВидыНоменклатуры.Товар)

ГДЕ ТипНоменклатуры= Значение(Перечисление.ТипыНоменклатуры.Услуга)

ТИП в запросе

Тип данных можно проверить следующим образом: с помощью функций ТИП() и ТИПЗНАЧЕНИЯ() или с помощью логического оператора ССЫЛКА.

ВЫРАЗИТЬ()

Оператор Выразить в запросах 1С служит для преобразования типов данных.

Синтаксис: ВЫРАЗИТЬ(<Выражение> КАК <Тип значения>)

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

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

ВЫБРАТЬ
КонтактнаяИнформация.Объект,
ВЫРАЗИТЬ(КонтактнаяИнформация.Представление КАК СТРОКА(150)) КАК Представление
ИЗ
РегистрСведений.КонтактнаяИнформация КАК КонтактнаяИнформация

СГРУППИРОВАТЬ ПО
ВЫРАЗИТЬ(КонтактнаяИнформация.Представление КАК СТРОКА(150)),
КонтактнаяИнформация.Объект

ЕСТЬNULL (ISNULL)

Достаточно полезная функция языка запросов 1С, которая проверяет значение в записи, и если оно равно NULL, то позволяет заменить на своё значение. Чаще всего используется при получении виртуальных таблиц остатков и оборотов, чтобы скрыть NULL и поставить понятный 0 (ноль).

ЕСТЬNULL(НалогиПредМесяца.ПримененнаяЛьготаФСС, 0)

Такая функция языка запросов 1С ЕСТЬNULL при отсутствии значения вернет ноль, что позволит избежать ошибки.

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

Соединения бывают 4 типов: ЛЕВОЕ , ПРАВОЕ , ПОЛНОЕ, ВНУТРЕННЕЕ .

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

Соединения используются для связи двух таблиц по определенному условию. Особенность при ЛЕВОМ СОЕДИНЕНИИ в том, что мы берём первую указанную таблицу полностью и привязываем по условию вторую таблицу. Поля второй таблицы, которые не удалось привязать по условию, заполняются значением NULL .

Пример левого соединения в запросе 1С:

Вернет всю таблицу и заполнит поле «Банк» лишь в тех местах, где будет соблюдаться условие «Контрагенты.Наименование = Банки.Наименование». Если условие не соблюдается, в поле Банк будет установлено NULL .

ПРАВОЕ СОЕДИНЕНИЕ в языке 1С 8.3 абсолютно аналогично ЛЕВОМУ соединению , за исключением одного отличия: в ПРАВОМ СОЕДИНЕНИИ «главная» таблица — вторая, а не первая.

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

ПОЛНОЕ СОЕДИНЕНИЕ отличается от левого и правого тем, что выводит все записи из двух таблиц, соединяет лишь те, которые может соединить по условию.

Например:

ПОЛНОЕ СОЕДИНЕНИЕ
Справочник.Банки КАК Банки

ПО

Язык запросов вернет обе таблицы полностью лишь по выполненному условию Соединить записи. В отличие от левого/правого соединения возможно появления NULL в двух полях.

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

ВНУТРЕННЕЕ СОЕДИНЕНИЕ отличается от полного тем, что выводит только те записи, которые смогли соединить по заданному условию.

Например:

ИЗ
Справочник.Контрагенты КАК Клиенты

ВНУТРЕННЕЕ СОЕДИНЕНИЕ
Справочник.Банки КАК Банки

ПО
Клиенты.Наименование = Банки.Наименование

Данный запрос вернет только строки, в которых у банка и контрагента будет одинаковое наименование.

Заключение

Это лишь небольшая часть синтаксиса из языка запросов 1С 8, в дальнейшем я попробую рассмотреть более подробно некоторые моменты, показать и многое другое!

Вопрос Обход запроса по группировкам, как собираются данные в запросе с конструкцией ИТОГИ ПО. Предположим, требуется организовать цикл, в котором должен формироваться массив заказов, в разрезе Контрагентов и Адреса доставки. Как это сделать?
Ответ Пишем запрос:

1С (Код)

Запрос.Текст = "ВЫБРАТЬ // Адрес доставки заключаем в "ВЫРАЗИТЬ", т.к. в метаданных Адрес Доставки - строка неограниченной длины и если ее не преобразовать в строку ограниченной длины, //то ее будет невозможно использовать в конструкции "ИТОГИ ПО" // и мы получим сообщение об ошибке вида "Недопустимое поле для группировки" |ИЗ |ГДЕ | усЗаказНаОтгрузку.Проведен | |УПОРЯДОЧИТЬ ПО |ИТОГИ ПО | Контрагент, | АдресДоставки";

Запрос< spanclass="k" > . < /span> Текст< spanclass="k" > =< /span>

< spanclass="s" > "ВЫБРАТЬ

| усЗаказНаОтгрузку.Ссылка КАК Ссылка,

| усСтатусДокументов.Статус КАК Статус,

| усЗаказНаОтгрузку.Контрагент КАК Контрагент,

// Адрес доставки заключаем в " ВЫРАЗИТЬ", т.к. в метаданных Адрес Доставки - строка неограниченной длины и если ее не преобразовать в строку ограниченной длины,

//то ее будет невозможно использовать в конструкции " ИТОГИ ПО"

// и мы получим сообщение об ошибке вида " < strong> Недопустимоеполедля группировки< /strong> "

| ВЫРАЗИТЬ(усЗаказНаОтгрузку.АдресДоставки КАК СТРОКА(350)) КАК АдресДоставки

|ИЗ

| РегистрСведений.усСтатусДокументов КАК усСтатусДокументов

| ЛЕВОЕ СОЕДИНЕНИЕ Документ.усЗаказНаОтгрузку КАК усЗаказНаОтгрузку

| ПО усСтатусДокументов.Документ = усЗаказНаОтгрузку.Ссылка

|ГДЕ

| усЗаказНаОтгрузку.Проведен

|

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

| усСтатусДокументов.Статус.Порядок

|ИТОГИ ПО

| Контрагент,

| АдресДоставки" < /span> < spanclass="k" > ; < /span>

Результатом этого запроса будет набор данных примерно такого вида:

Контрагент 1

  • АдресДоставки1

Контрагент 1

  • АдресДоставки2

Контрагент2

  • АдресДоставки3

Теперь нам нужно получить три массива:
— заказ 1, заказ 2, заказ 3
— заказ 4, заказ 5
— заказ 6
Для получения этих массивов требуется организовать обход приведенного выше запроса «По группировкам с иерархией»:

1С (Код)

СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией; Результат = Запрос.Выполнить(); ВыборкаПервогоУровня = Результат.Выбрать(СпособВыборки); Пока ВыборкаПервогоУровня.Следующий() Цикл ВыборкаВторогоУровня = ВыборкаПервогоУровня.Выбрать(СпособВыборки); мсвЗаказов.Очистить(); Пока ВыборкаВторогоУровня.Следующий() Цикл // внутри каждого уровня иерархии заказы упорядочены: "Создан", "В работу", "Ведутся работы", "Готов к отгрузке" (именно в таком порядке, порядок установлен в перечислении) ВыборкаТретьегоУровня = ВыборкаВторогоУровня.Выбрать(ОбходРезультатаЗапроса.Прямой); Пока ВыборкаТретьегоУровня.Следующий() Цикл // внутри каждого уровня иерархии заказы упорядочены: "Создан", "В работу", "Ведутся работы", "Готов к отгрузке" (именно в таком порядке, порядок установлен в перечислении) мсвЗаказов.Добавить(ВыборкаТретьегоУровня.Ссылка); КонецЦикла; СформироватьОтборПоЗаказу(мсвЗаказов); КонецЦикла; КонецЦикла;

СпособВыборки < spanclass="k" > =< /span> ОбходРезультатаЗапроса< spanclass="k" > . < /span> ПоГруппировкамСИерархией< spanclass="k" > ; < /span>

Результат< spanclass="k" > =< /span> Запрос< spanclass="k" > . < /span> < spanclass="k" > Выполнить< /span> < spanclass="k" > (< /span> < spanclass="k" > ) < /span> < spanclass="k" > ; < /span>

ВыборкаПервогоУровня< spanclass="k" > =< /span> Результат< spanclass="k" > . < /span> Выбрать< spanclass="k" > (< /span> СпособВыборки< spanclass="k" > ) < /span> < spanclass="k" > ; < /span>

< spanclass="k" > Пока< /span> ВыборкаПервогоУровня< spanclass="k" > . < /span> Следующий< spanclass="k" > (< /span> < spanclass="k" > ) < /span> < spanclass="k" > Цикл< /span> < spanclass="c" > // внутри каждого уровня иерархии заказы упорядочены: "Создан", "В работу", "Ведутся работы", "Готов к отгрузке" (именно в таком порядке, порядок установлен в перечислении)

ВыборкаВторогоУровня< spanclass="k" > =< /span> ВыборкаПервогоУровня< spanclass="k" > . < /span> Выбрать< spanclass="k" > (< /span> СпособВыборки< spanclass="k" > ) < /span> < spanclass="k" > ; < /span>

мсвЗаказов< spanclass="k" > . < /span> Очистить< spanclass="k" > (< /span> < spanclass="k" > ) < /span> < spanclass="k" > ; < /span> < spanclass="c" > // очистили перед добавлением первого в список

< spanclass="k" > Пока< /span> ВыборкаВторогоУровня< spanclass="k" > . < /span> Следующий< spanclass="k" > (< /span> < spanclass="k" > ) < /span> < spanclass="k" > Цикл< /span> < spanclass="c" > // внутри каждого уровня иерархии заказы упорядочены: "Создан", "В работу", "Ведутся работы", "Готов к отгрузке" (именно в таком порядке, порядок установлен в перечислении)

ВыборкаТретьегоУровня< spanclass="k" > =< /span> ВыборкаВторогоУровня< spanclass="k" > . < /span> Выбрать< spanclass="k" > (< /span> ОбходРезультатаЗапроса< spanclass="k" > . < /span> Прямой< spanclass="k" > ) < /span> < spanclass="k" > ; < /span> < spanclass="c" > // параметр можно не передавать, по умолчанию способ выборки прямой

< spanclass="k" > Пока< /span> ВыборкаТретьегоУровня< spanclass="k" > . < /span> Следующий< spanclass="k" > (< /span> < spanclass="k" > ) < /span> < spanclass="k" > Цикл< /span> < spanclass="c" > // внутри каждого уровня иерархии заказы упорядочены: "Создан", "В работу", "Ведутся работы", "Готов к отгрузке" (именно в таком порядке, порядок установлен в перечислении)

мсвЗаказов< spanclass="k" > . < /span> Добавить< spanclass="k" > (< /span> ВыборкаТретьегоУровня< spanclass="k" > . < /span> Ссылка< spanclass="k" > ) < /span> < spanclass="k" > ; < /span>

< spanclass="k" > КонецЦикла< /span> < spanclass="k" > ; < /span>

СформироватьОтборПоЗаказу< spanclass="k" > (< /span> мсвЗаказов< spanclass="k" > ) < /span> < spanclass="k" > ; < /span> < spanclass="c" > // тут мы по очереди получим в цикле требуемые массивы: [заказ 1, заказ 2, заказ 3], затем [заказ 4, заказ 5] и [заказ 6]

< spanclass="k" > КонецЦикла< /span> < spanclass="k" > ; < /span>

< spanclass="k" > КонецЦикла< /span> < spanclass="k" > ; < /span>

Примечание. Конструкция «УПОРЯДОЧИТЬ ПО усСтатусДокументов.Статус.Порядок» будет срабатывать внутри каждого массива, т.е. заказы будут упорядочены по статусу в каждом из полученных массивов.

Справка по расчету итогов запроса из описания в справке Конфигуратора

Расчет итогов запроса

Предложение ИТОГИ позволяет определить, расчет каких итогов необходим в запросе. При расчете итогов вычисляются значения агрегатных функций по выборкам с одинаковыми значениями полей – контрольных точек. Итоги добавляются в результат запроса как итоговые строки.

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

<Описание итогов>

<Итоги> [<Список агрегатных функций>]

<Итоги>

ИТОГИ [<Список итоговых_полей>] ПО [ОБЩИЕ] <Список контрольных точек>

<Список итоговых_полей>

<Итоговое_поле> [,<Список_итоговых_полей> [, …]]

<Итоговое_поле>

<Агрегатная_функция> | <Выражение> [[КАК] <Псевдоним_поля>]

<Список контрольных точек>

<Контрольная точка> [, <Контрольная точка> [, …]]

<Контрольная точка>

<Выражение> [[ТОЛЬКО] ИЕРАРХИЯ] | [ПЕРИОДАМИ(Секунда | Минута | Час | День | Неделя | Месяц | Квартал | Год | Декада | Полугодие
[,<Литерал типа DATE> | <Идентификатор параметра>]
[,<Литерал типа DATE> | <Идентификатор параметра>])] [[КАК] Псевдоним поля]

Описание итогов начинается с обязательного ключевого слова ИТОГИ.

<Список агрегатных функций> содержит перечень агрегатных функций, которые необходимо рассчитывать в итогах. Агрегатные функции рассматриваются в .

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

Если контрольная точка является полем — субконто регистра бухгалтерии, то при получении итогов по этой контрольной точке будут игнорироваться значения NULL.

Агрегатные функции языка запросов

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

<Агрегатная функция>

СУММА (<Выражение>) |
СРЕДНЕЕ (<Выражение>) |
МИНИМУМ (<Выражение>) |
МАКСИМУМ (<Выражение>) |
КОЛИЧЕСТВО ([РАЗЛИЧНЫЕ] <Выражение> | *)

Пример:

Выбрать
Накладная.Номенклатура.Наименование,
Сумма (Накладная.Сумма) Как Сумма,
Среднее (Накладная.Сумма) Как Среднее,
Максимум (Накладная.Сумма) Как Максимум,
Минимум (Накладная.Сумма) Как Минимум,
Количество (Накладная.Сумма) Как Колич

Из

Сгруппировать По
Накладная.Номенклатура

Итоги Общие

Результат запроса:

Наименование Сумма Среднее Максимум Минимум Колич
265 955,45 12 511,12 40 000,23 555 8
Брюки детские 28 500,22 9 500,07 15 000 3 000 3
Рубашка «Ковбойка» 24 000 8 000 16 000 4 000 3
Джинсы женские 63 555 6 355,5 30 000 555 10
Свитер детский 6 400 6 400 6 400 6 400 1
Раковина «Лилия» 60 000,23 30 000,115 40 000,23 20 000 2
Мойдодыр «Аквариум» 65 500 21 833,33 40 000 8 000 3
Смеситель «Ультра» 15 000 15 000 15 000 15 000 1
Кухонный комбайн Крупс 3 000 3 000 3 000 3 000 1

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

Агрегатная функция СУММА

Функция вычисляет арифметическую сумму всех попавших в выборку значений поля.

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

Если поле не может содержать числовых значений, то применение функции СУММА к такому полю вызовет ошибку. Если поле может содержать числовые значения (имеет составной тип данных), то данная функция может быть применена к такому полю. Но если среди значений поля в выборке встретится нечисловое значение (помимо значений NULL), это вызовет ошибку.

Агрегатная функция СРЕДНЕЕ

Функция вычисляет среднее значение всех попавших в выборку значений поля.

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

Если поле не может содержать числовых значений, то применение функции СРЕДНЕЕ к такому полю вызовет ошибку. Если поле может содержать числовые значения (имеет составной тип данных), то данная функция может быть применена к такому полю. Но если среди значений поля в выборке встретится нечисловое значение (помимо значений NULL), это вызовет ошибку.

Агрегатная функция МИНИМУМ

Функция вычисляет минимальное значение из всех попавших в выборку значений поля.

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

Агрегатная функция МАКСИМУМ

Функция вычисляет максимальное значение из всех попавших в выборку значений поля.

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

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

Агрегатная функция КОЛИЧЕСТВО

Функция подсчитывает количество значений параметра, попавших в выборку. В отличие от других агрегатных функций функция КОЛИЧЕСТВО допускает три способа использования.

  • Во-первых, функция позволяет подсчитать количество значений указанного поля, не равных NULL.
  • Во-вторых, функция позволяет подсчитать количество различных значений указанного поля, не равных NULL. Для этого перед спецификацией поля надо указать ключевое слово РАЗЛИЧНЫЕ.
  • В-третьих, функция позволяет подсчитать количество строк в результате запроса. Для этого в качестве параметра функции надо указать звездочку «*».

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

Пример:

ВЫБРАТЬ
Количество (*) Как Всего,
Количество (Различные Накладная.Номенклатура) Как Разные

Из
Документ.РасходнаяНакладная.Состав Как Накладная

Результат запроса:

Всего Разные
24 8

Расчет общих итогов

Для расчета итогов по всей таблице в предложении ИТОГИ следует указать слово ОБЩИЕ. В этом случае будут вычислены значения агрегатных функций для всех записей таблицы.

Пример:



ИТОГИ СУММА(Количество) По ОБЩИЕ

Результат запроса:

Товар Количество Номер Получатель
238
Кран 10 РНк-1 Урюпинскторг
Кран 8 РНк-3 Маг. «Хозяин»
Кран 44 РНк-4 Маг. «Гигант»
Кран 22 РНк-5 Урюпинскторг
Вантус 5 РНк-1 Урюпинскторг
Вантус 1 РНк-3 Маг. «Хозяин»
Вантус 14 РНк-4 Маг. «Гигант»
Стол 1 РНк-1 Урюпинскторг
Стол 15 РНк-2 Маг. «Мебель»
Стол 10 РНк-4 Маг. «Гигант»
Стул 55 РНк-2 Маг. «Мебель»
Стул 5 РНк-3 Маг. «Хозяин»
Стул 32 РНк-4 Маг. «Гигант»
Стул 16 РНк-5 Урюпинскторг

Логические выражения в языке запросов

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

<Логическое выражение>

<Выражение> |
<Выражение> <Операция сравнения> <Выражение> |
<Выражение> [НЕ] В [ИЕРАРХИИ] (<Список значений> | <Массив значений>) |
<Выражение> [НЕ] В [ИЕРАРХИИ] (<Описание запроса>) |
<Выражение> [НЕ] МЕЖДУ <Выражение> И <Выражение> |
<Выражение> ЕСТЬ [НЕ] NULL |
<Выражение> ССЫЛКА <Имя таблицы> |
<Выражение> [НЕ] ПОДОБНО <Литерал типа СТРОКА>
[СПЕЦСИМВОЛ <Литерал типа СТРОКА>]

<Операция сравнения>

> | < | = | >= | <= | <>

<Список значений>

<Выражение>[, <Выражение> [, …]]

Логическим выражением может быть:

При сравнении значений используются правила сравнения значений, описанные ниже.

Правила сравнения значений

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

  • сравнения значений в операторах сравнения;
  • определения максимального и минимального значений в агрегатных функциях МИНИМУМ и МАКСИМУМ;
  • упорядочивания записей результата запроса в соответствии с порядком, заданным в предложении УПОРЯДОЧИТЬ ПО.

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

  • тип NULL (самый низший);
  • тип Булево;
  • тип Число;
  • тип Дата;
  • тип Строка;
  • ссылочные типы.

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

Если типы данных совпадают, то производится сравнение значений по следующим правилам:

  • у типа Булево значение ИСТИНА больше значения ЛОЖЬ;
  • у типа Число обычные правила сравнения для чисел;
  • у типа Дата более ранние даты меньше более поздних;
  • у типа Строка сравнения производится в соответствии с установленными национальными особенностями базы данных без учета концевых пробелов;
  • ссылочные типы сравниваются на основе своих значений (номера записи и т. п.);
  • не допускается сравнение полей неограниченной длины (строки неограниченной длины, ХранилищеЗначения, поле ТипЗначения из таблицы планов видов характеристик).

Важно! Любая операция сравнения двух значений, в которой участвует хотя бы одно значение NULL, дает результат, аналогичный значению ЛОЖЬ.

Оператор проверки совпадения значения

Форма оператора В для проверки совпадения с одним из перечисленных

Оператор В позволяет проверить, совпадает ли значение выражения, указанного справа от него, с одним из значений, описанных слева. Если совпадает хотя бы с одним – результатом оператора будет ИСТИНА, иначе – ЛОЖЬ. Применение НЕ изменяет действие оператора на обратное. Сравнение значений производится по правилам, описанным в .

Пример:

Выбрать

Где
Справочник.Номенклатура.Родитель.Наименование
В («Бытовая техника», «Оргтехника»)

Форма оператора В для проверки принадлежности по иерархии

Для справочников проверка может осуществляться и на принадлежность по иерархии. Результатом оператора В ИЕРАРХИИ будет ИСТИНА, если значение выражения слева является ссылкой на элемент справочника и входит во множество значений справа или иерархически принадлежит какой-нибудь группе, содержащейся в этом множестве:

Пример:

// В качестве параметра Группа в запрос передается ссылка
// на какую-либо группу справочника Номенклатура.

Выбрать
Справочник.Номенклатура.Наименование

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

Пример:

Выбрать
Справочник.Номенклатура.Наименование

Форма оператора В для проверки совпадения значения с одним из результата запроса

Примером применения данного оператора может послужить следующее:

Пример:


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

)

Результат запроса:

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

Пример:

// Выбрать названия товаров, которые присутствовали в расходных накладных
ВЫБРАТЬ
Товары.Наименование
ИЗ
Справочник.Товары КАК Товары
ГДЕ
Товары.Ссылка НЕ В
ВЫБРАТЬ
РасхНаклСостав.Товар
ИЗ
Документ.РасхНакл.Состав КАК РасхНаклСостав
)

Результат запроса:

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

Пример:

// Выбрать названия товаров, которые присутствовали в расходных накладных
ВЫБРАТЬ
Товары.Наименование
ИЗ
Справочник.Товары КАК Товары
ГДЕ
Товары.Ссылка В
ВЫБРАТЬ
РасхНаклСостав.Товар
ИЗ
Документ.РасхНакл.Состав КАК РасхНаклСостав
ГДЕ
РасхНаклСостав.Товар = Товары.Ссылка
)

Результат запроса:

Оператор проверки вхождения значения в диапазон

Оператор МЕЖДУ позволяет проверить, входит ли значение выражения, указанного справа от него, в диапазон, указанный слева (вместе с границами диапазона). Если входит – результатом оператора будет ИСТИНА, иначе – ЛОЖЬ. Применение НЕ изменяет действие оператора на обратное. Сравнение значений производится по правилам, описанным в .

Пример:

Выбрать


Где
Справочник.Номенклатура.ЗакупочнаяЦена МЕЖДУ 100 И 1000

Оператор проверки значения на NULL

Оператор ЕСТЬ NULL позволяет проверить значение выражения слева от него на NULL. Если значение равно NULL – результатом оператора будет ИСТИНА, иначе – ЛОЖЬ. Применение НЕ изменяет действие оператора на обратное.

Пример:

Выбрать
Справочник.Номенклатура.Наименование,
Справочник.Номенклатура.ЗакупочнаяЦена
Где
Справочник.Номенклатура.ЗакупочнаяЦена Есть NULL

Оператор проверки ссылочного значения

Оператор ССЫЛКА позволяет проверить, является ли значение выражения, указанного справа от него, ссылкой на таблицу, указанную слева. Если да – результатом оператора будет ИСТИНА, иначе – ЛОЖЬ. Разыменование таблиц описано в параграфе «Разыменование полей».

Пример:

Выбрать
Справочник.Номенклатура.Наименование,
Справочник.Номенклатура.ЕдиницаИзмерения
Где
Справочник.Номенклатура.ЕдиницаИзмерения Ссылка Справочник.ЕдиницыИзмерения

Оператор проверки строки на подобие шаблону

Оператор ПОДОБНО позволяет сравнить значение выражения, указанного слева от него, со строкой шаблона, указанной справа. Значение выражения должно иметь тип строка. Если значение выражения удовлетворяет шаблону – результатом оператора будет ИСТИНА, иначе – ЛОЖЬ.

Следующие символы в строке шаблона являются служебными и имеют смысл, отличный от символа строки:

  • % (процент): последовательность, содержащая любое количество произвольных символов
  • _ (подчеркивание): один произвольный символ
  • […] (в квадратных скобках один или несколько символов): любой одиночный символ из перечисленных внутри квадратных скобок
    В перечислении могут встречаться диапазоны, например a-z, означающие произвольный символ, входящий в диапазон, включая концы диапазона.
  • [^…] (в квадратных скобках значок отрицания, за которым следует один или несколько символов): любой одиночный символ, кроме тех, которые перечислены следом за значком отрицания

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

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

Например, шаблон “%АБВ[абвг]_абв%” СПЕЦСИМВОЛ “” означает подстроку, состоящую из последовательности символов:
буквы А; буквы Б; буквы В; одной цифры; одной из букв а, б, в или г; символа подчеркивания; буквы а; буквы б; буквы в.

Причем перед этой последовательностью может располагаться произвольный набор символов.

Итоги по иерархии

Есть возможность рассчитать итоги по иерархии. Для этого после имени поля, для которого вычисляются итоги необходимо указать ключевое слово ИЕРАРХИЯ. В результате будут рассчитаны итоги по контрольным точкам и итоги по иерархии для контрольных точек.

Пример:

ВЫБРАТЬ Док.Товар, Док.Количество, Док.Ссылка.Номер, Док.Ссылка.Получатель
ИЗ Документ.РасхНакл.Состав Как Док
УПОРЯДОЧИТЬ ПО Док.Товар
ИТОГИ СУММА(Количество) ПО Док.Товар ИЕРАРХИЯ

Результат запроса:

Товар Количество Номер Получатель
Сантехника 104
Кран 84
Кран 10 РНк-1 Урюпинскторг
Кран 8 РНк-3 Маг. “Хозяин”
Кран 44 РНк-4 Маг. “Гигант”
Кран 22 РНк-5 Урюпинскторг
Вантус 20
Вантус 5 РНк-1 Урюпинскторг
Вантус 1 РНк-3 Маг. “Хозяин”
Вантус 14 РНк-4 Маг. “Гигант”
Мебель 134
Стол 26
Стол 1 РНк-1 Урюпинскторг
Стол 15 РНк-2 Маг. “Мебель”
Стол 10 РНк-4 Маг. “Гигант”
Стул 108
Стул 55 РНк-2 Маг. “Мебель”
Стул 5 РНк-3 Маг. “Хозяин”
Стул 32 РНк-4 Маг. “Гигант”
Стул 16 РНк-5 Урюпинскторг

Пример:

ВЫБРАТЬ Док.Товар, Док.Количество, Док.Ссылка.Номер, Док.Ссылка.Получатель
ИЗ Документ.РасхНакл.Состав Док
УПОРЯДОЧИТЬ ПО Док.Товар
ИТОГИ СУММА(Количество) ПО Док.Товар ТОЛЬКО ИЕРАРХИЯ

Результат запроса:

Товар Количество Номер Получатель
Сантехника 104
Кран 10 РНк-1 Урюпинскторг
Кран 8 РНк-3 Маг. “Хозяин”
Кран 44 РНк-4 Маг. “Гигант”
Кран 22 РНк-5 Урюпинскторг
Вантус 5 РНк-1 Урюпинскторг
Вантус 1 РНк-3 Маг. “Хозяин”
Вантус 14 РНк-4 Маг. “Гигант”
Мебель 134
Стол 1 РНк-1 Урюпинскторг
Стол 15 РНк-2 Маг. “Мебель”
Стол 10 РНк-4 Маг. “Гигант”
Стул 55 РНк-2 Маг. “Мебель”
Стул 5 РНк-3 Маг. “Хозяин”
Стул 32 РНк-4 Маг. “Гигант”
Стул 16 РНк-5 Урюпинскторг
Posted in , Tagged #

Предположим, что на наших складах имеется такой товар:

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

Запрос.Текст = "
|ВЫБРАТЬ
| Товары.Товар,
| СУММА(Товары.Количество) КАК Количество
|ИЗ
|
|СГРУППИРОВАТЬ ПО
| Товары.Товар";

Товар в данном случае - это поле по которому осуществляется группировка, а Количество - группируемое поле. СУММА - это агрегатная функция, она указывает запросу что все данные по количеству одинаковых товаров нужно просуммировать. Результатом выполнения этого запроса будет таблица вида:

Агрегатные функции

К группируемым полям должны быть обязательно применена агрегатная функция, это необязательно СУММА, а также МАКСИМУМ, МИНИМУМ, СРЕДНЕЕ, КОЛИЧЕСТВО, КОЛИЧЕСТВО РАЗЛИЧНЫХ. Рассмотрим более подробно действие каждой из них.

СУММА - применяется только для числовых полей, складывает переданные ей числа. Ее результат приведен на рисунке выше.

СРЕДНЕЕ - применяется только для числовых полей, вычисляет среднее - сумма переданных параметров / количество параметров:

МАКСИМУМ - может использоваться для любых полей, получает максимальный из переданных параметров. Допустим текст запроса имеет вид:

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

Т.е. имеем опять одно группировочное поле Товар и два группируемых поля: Склад и Количество. Результат выполнения этого запроса будет выглядеть следующим образом:

МИНИМУМ - может использоваться для любых полей, получает минимальный из переданных параметров:

КОЛИЧЕСТВО - может использоваться для любых полей, получает количество переданных параметров:

КОЛИЧЕСТВО РАЗЛИЧНЫХ - может использоваться для любых полей, получает количество различных параметров. Т.е. если функции передать параметры (1,1,2,3,3,3,4,4,4,4,4,5), то она вернет 5 . Функция КОЛИЧЕСТВО вернула бы 12. Запрос с использованием функции КОЛИЧЕСТВО РАЗЛИЧНЫХ будет выглядеть так:

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

Результат:

Пусть мы группируем по двум полям: Товар и Склад:

Запрос.Текст = "
|ВЫБРАТЬ
| Товары.Товар,
| Товары.Склад КАК Склад,
| <АГРЕГАТНАЯ ФУНКЦИЯ>(Товары.Количество) КАК Количество
|ИЗ
| Справочник.Товары КАК Товары
|СГРУППИРОВАТЬ ПО
| Товары.Товар,
| Товары.Склад";

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

Подведем итоги:

Если в запросе используется группировка, то все поля должны делиться на группируемые (которые будут "свернуты") и группировочные (по которым осуществляется группировка - "сворачивание"). К группируемым полям должна быть применена одна из агрегатных функций, причем такие функции как СУММА и СРЕДНЕЕ могут быть применены только к числовым полям.

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

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);

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

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

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

ПОМЕСТИТЬ ТЗ

ИЗ &ТЗ КАК ТЗ

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

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

ИЗ ТЗ КАК ТЗ

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

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

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

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