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

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

1. Конструкция "ИЗ".

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

ВЫБРАТЬ Справочник.Банки.*

Выбирает все поля из справочника Банки. И является аналогичным запросу:

ВЫБРАТЬ Банки.* ИЗ Справочник.Банки КАК Банки

2. Упорядочивание данных по ссылочному полю

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

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

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

3.Получение текстового представления ссылочного типа. Конструкция "ПРЕДСТАВЛЕНИЕ".

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

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

4. Условие на выборку данных по шаблону.

Например, вам необходимо получить мобильные телефоны сотрудников вида (8 -123- 456-78-912). Для этого необходимо поставить такое условие в запросе:

ВЫБРАТЬ Сорудник.Наименование, Сорудник.Телефон КАК Телефон ИЗ Справочник.Сотрудники КАК Сотрудники ГДЕ Телефон ПОДОБНО "_-___-___-__-__"

Символ "_" является служебным и заменяет любой символ.

5. Одновременное использование итогов и группировок.


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

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

В этом случае запрос вернет практически тоже самое что и такой запрос:

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

Только первый запрос свернет записи с одинаковой номенклатурой.

6. Разыменование полей.

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

Запрос:

Можно представить в виде:

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

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

Например имеется регистр накопления "Нераспределенные оплаты", где регистратором могут выступать несколько документов. В этом случае неверно получать значения реквизитов регистратора таким образом:

ВЫБРАТЬ НераспределенныеОплаты.Регистратор.Дата, ..... ИЗ РегистрНакопления.НераспределеныеОплаты КАК НераспределенныеОплаты

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

ВЫБРАТЬ ВЫРАЗИТЬ(НераспределенныеОплаты.Регистратор КАК Документ.Оплата).Дата, ..... ИЗ РегистрНакопления.НераспределеныеОплаты КАК НераспределенныеОплаты

7. Конструкция "ГДЕ"

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

Пример. Необходимо выбрать всех Клиентов из Справочника клиенты и для тех клиентов, у которых имеется документ оплата со значением реквизита "Организация" = &Организация вывести документ "Оплата", для тех у кого нет, не выводить.

Результат запроса вернет записи только для тех клиентов, у которых была оплата по организации в параметре, а других клиентов отсеет. Поэтому необходимо сначала получить все оплаты по "такой-то" организации во временной таблице, а потом уже соединять со справочником "Клиенты" левым соединением.

ВЫБРАТЬ Оплата.Ссылка КАК Оплата, Оплата.Пайщик КАК Клиент ПОМЕСТИТЬ тОплаты ИЗ Документ.Оплата КАК Оплата ГДЕ Оплата.Отделение = &Отделение; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Клиенты.Ссылка КАК Клиент, ЕСТЬNULL(тОплаты.Оплата, "") КАК Оплата ИЗ Справочник.Клиенты КАК Клиенты ЛЕВОЕ СОЕДИНЕНИЕ тОплаты КАК тОплаты ПО Клиенты.Ссылка = тОплаты.Клиент

Можно обойти это условие и другим способом. необходимо наложить условие "ГДЕ" непосредственно в связи двух таблиц. Пример:

ВЫБРАТЬ Клиенты.Ссылка, Оплата.Ссылка ИЗ Справочник.УС_Абоненты КАК УС_Абоненты ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата ПО (Клиенты.Ссылка = Оплата.Клиент И Оплата.Клиент.Наименование ПОДОБНО "Сахарный Пакет") СГРУППИРОВАТЬ ПО Клиенты.Ссылка, Оплата.Ссылка

8. Соединения с Вложенными и Виртуальными таблицами

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

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

ВЫБРАТЬ НераспределенныеОплатыОстатки.Клиент, НераспределенныеОплатыОстатки.СуммаОстаток ИЗ (ВЫБРАТЬ Клиенты.Ссылка КАК Ссылка ИЗ Справочник.Клиенты КАК Клиенты ГДЕ Клиенты.Ссылка В(&Клиенты)) КАК ВложенныйЗапрос ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.НераспределенныеОплаты.Остатки КАК НераспределенныеОплаты ПО ВложенныйЗапрос.Ссылка = НераспределенныеОплатыОстатки.Клиент

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

ВЫБРАТЬ Клиенты.Ссылка КАК Ссылка ПОМЕСТИТЬ тКлиенты ИЗ Справочник.Клиенты КАК Клиенты ГДЕ
Клиенты.Ссылка В (&Клиенты) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ тКлиенты.Ссылка, НераспределенныеОплатыОстатки.СуммаОстаток, ИЗ тКлиенты КАК тКлиенты ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.НераспределенныеОплаты.Остатки(, Клиент В (ВЫБРАТЬ тКлиенты.Ссылка ИЗ тКлиенты)) КАК НераспределенныеОплатыОстатки ПО тКлиенты.Ссылка = НераспределенныеОплатыОстатки.Клиенты

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

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

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

ВЫБРАТЬ Клиенты.Ссылка КАК Ссылка ПОМЕСТИТЬ тКлиенты ИЗ Справочник.Клиенты КАК Клиенты ИНДЕКСИРОВАТЬ ПО Ссылка ГДЕ
Клиенты.Ссылка В (&Клиенты) ; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ НераспределенныеОплаты.СуммаОстаток, НераспределенныеОплаты.Клиент КАК Клиент ПОМЕСТИТЬ тОстатки ИЗ РегистрНакопления.НераспределенныеОплаты.Остатки(, Клиент В (ВЫБРАТЬ тКлиенты.Ссылка ИЗ тКлиенты)) КАК НераспределенныеОплатыОстатки; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ тКлиенты.Ссылка, тОстатки.СуммаОстаток КАК СуммаОстаток ИЗ тКлиенты КАК тКлиенты ЛЕВОЕ СОЕДИНЕНИЕ тОстатки КАК тОстатки ПО тКлиенты.Ссылка = тОстатки.Клиент

9.Проверка результата выполнения запроса.

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

РезЗапроса = Запрос.Выполнить(); Если резЗапроса.Пустой() Тогда Возврат; КонецЕсли;

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

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

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

Это избавит систему от синтаксической проверки запроса в цикле.

11. Конструкция "ИМЕЮЩИЕ".

Конструкция, довольно редко встречающаяся в запросах. Позволяет накладывать условия на значения агрегатные функций (СУММА, МИНИМУМ, СРЕДНЕЕ и т.д.). Например, вам необходимо выбрать только тех клиентов, у которых сумма оплат в сентябре была больше 13 000 рублей. Если использовать условие "ГДЕ", то придется сначала создавать временную таблицу или вложенный запрос, там группировать записи по сумме оплаты и потом накладывать условие. Конструкция "ИМЕЮЩИЕ" поможет этого избежать.

ВЫБРАТЬ Оплата.Клиент, СУММА(Оплата.Сумма) КАК Сумма ИЗ Документ.Оплата КАК Оплата ГДЕ МЕСЯЦ(Оплата.Дата) = 9 СГРУППИРОВАТЬ ПО Оплата.Клиент ИМЕЮЩИЕ СУММА(Оплата.Сумма) > 13000

В конструкторе для этого достаточно перейти на вкладку "Условия", добавить новое условие и поставить галочку на "Произвольное". Далее просто написать Сумма(Оплата.Сумма) > 13000


12. Значение NULL

Я не буду описывать здесь принципы трехзначной логики в БД, есть множество статей на эту тему. Просто вкратце о том как NULL может повлиять на результат запроса. Значение NULL на самом деле не значение, а факт того, что значение не определено, неизвестно. Поэтому любые операции с NULL возвращают NULL, будь то сложение, вычитание, деление или сравнение. Значение NULL не может быть сравнимо со значением NULL, потому как мы не знаем, что именно сравнивать. Т.е. оба этих сравнения: NULL = NULL, NULL<>NULL - это не Истина или не Ложь, это неизвестно.

Давайте рассмотрим пример.

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

ВЫБРАТЬ "Нет оплат" КАК Признак, NULL КАК Документ ПОМЕСТИТЬ тОплаты; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Клиенты.Ссылка КАК Клиент, Оплата.Ссылка КАК Оплата ПОМЕСТИТЬ тКлиентОплата ИЗ Справочник.Клиенты КАК Клиенты ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата ПО Клиенты.Ссылка = Оплата.Пайщик; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ тКлиентОплата.Клиент ИЗ тКлиентОплата КАК тКлиентОплата ВНУТРЕННЕЕ СОЕДИНЕНИЕ тОплаты КАК тОплаты ПО тКлиентОплата.Оплата = тОплаты.Документ

Обратите внимание на вторую временную таблицу тКлиентОплата. Левым соединением я выбираю всех клиентов и все оплаты по этим клиентам. Для тех же клиентов у которых нет оплат в поле "Оплата" будет NULL . Следуя логике, в первой временной таблице "тОплаты" я обозначил 2 поля, одно из них NULL, второе строка "Не имеет оплат". В третьей таблице я соединяю внутренним соединением таблицы "тКлиентОплата" и "тОплаты" по полям "Оплата" и "Документ". Мы знаем, что в первой таблице поле "Документ" это NULL, и во второй таблице у тех, у кого нет оплат в поле "Оплата" тоже NULL. Что же вернет нам такое соединение? А ничего не вернет. Потому как сравнение NULL = NULL не принимает значение Истина.

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

ВЫБРАТЬ "Нет оплат" КАК Признак, ЗНАЧЕНИЕ(Документ.Оплата.ПустаяСсылка) КАК Документ ПОМЕСТИТЬ тОплаты; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ Клиенты.Ссылка КАК Клиент, ЕСТЬNULL(Оплата.Ссылка, ЗНАЧЕНИЕ(Документ.Оплата.ПустаяСсылка)) КАК Оплата ПОМЕСТИТЬ тКлиентОплата ИЗ Справочник.Клиенты КАК Клиенты ЛЕВОЕ СОЕДИНЕНИЕ Документ.Оплата КАК Оплата ПО Клиенты.Ссылка = Оплата.Пайщик; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ тКлиентОплата.Клиент ИЗ тКлиентОплата КАК тКлиентОплата ВНУТРЕННЕЕ СОЕДИНЕНИЕ тОплаты КАК тОплаты ПО тКлиентОплата.Оплата = тОплаты.Документ

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

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

13. Недокументированная особенность конструкции "ВЫБОР КОГДА...ТОГДА....КОНЕЦ".

В том случае, когда необходимо описывать в запросе контрукцию "Условия", то мы используем стандартный синтаксис:

ВЫБРАТЬ ВЫБОР КОГДА Пользователи.Наименование = "Вася Пупкин" ТОГДА "Наш любимый сотрудник" ИНАЧЕ "Не знаем такого" КОНЕЦ КАК Поле1 ИЗ Справочник.Пользователи КАК Пользователи

А что делать, если, к примеру, нам надо получить название месяца в запросе? Писать огромную конструкцию в запросе некрасиво и долго, поэтому нас может выручить такая форма записи выше:

ВЫБОР МЕСЯЦ(УС_РасчетПотребления_ГрафикОбороты.ПериодРасчета) КОГДА 1 ТОГДА "Январь" КОГДА 2 ТОГДА "Февраль" КОГДА 3 ТОГДА "Март" КОГДА 4 ТОГДА "Апрель" КОГДА 5 ТОГДА "Май" КОГДА 6 ТОГДА "Июнь" КОГДА 7 ТОГДА "Июль" КОГДА 8 ТОГДА "Август" КОГДА 9 ТОГДА "Сентябрь" КОГДА 10 ТОГДА "Октябрь" КОГДА 11 ТОГДА "Ноябрь" КОГДА 12 ТОГДА "Декабрь" КОНЕЦ КАК Месяц

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

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


Для того, чтобы не плодить запросы, можно создать один большой запрос, разбить его на пакеты и работать уже с ним.
Например, мне нужно получить из справочника "Пользователи" поля: "ДатаРождения" и доступные роли для каждого пользователя. в выгрузить это в разные табличные части на форме. Конечно можно сделать это в одном запросе, тогда придется перебирать записи или сворачивать, а можно так:

ВЫБРАТЬ Пользователи.Ссылка КАК ФИО, Пользователи.ДатаРождения, Пользователи.Роль ПОМЕСТИТЬ втПользователи ИЗ Справочник.Пользователи КАК Пользователи; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ втПользователи.ФИО, втПользователи.ДатаРождения ИЗ втПользователи КАК втПользователи СГРУППИРОВАТЬ ПО втПользователи.ФИО, втПользователи.ДатаРождения; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ втПользователи.ФИО, втПользователи.Роль ИЗ втПользователи КАК втПользователи СГРУППИРОВАТЬ ПО втПользователи.ФИО, втПользователи.ДатаРождения

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

ТП_ДатыРождения = тПакет.Выгрузить();
ТП_Роли = тПакет.Выгрузить();

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

15. Условия в пакетном запросе

Например, у нас есть пакетный запрос, где сначало мы получаем поля: "Наименование, ДатаРождения, Код" из справочника "Пользователи" и хотим из справочника "ФизЛица" получить записи с условием по этим полям.

ВЫБРАТЬ Пользователи.ФизЛицо.Наименование КАК Наименование, Пользователи.ФизЛицо.ДатаРождения КАК ДатаРождения, Пользователи.ФизЛицо.Код КАК Код ПОМЕСТИТЬ втПользователи ИЗ Справочник.Пользователи КАК Пользователи; //////////////////////////////////////////////////////////////////////////////// ВЫБРАТЬ ФизическиеЛица.Ссылка КАК ФизЛицо ИЗ Справочник.ФизическиеЛица КАК ФизическиеЛица

Можно накложить условия таким образом:

ГДЕ ФизическиеЛица.Код В (ВЫБРАТЬ втПользователи.Код ИЗ втПользователи) И ФизическиеЛица.Наименование В (ВЫБРАТЬ втПользователи.Код ИЗ втПользователи) И ФизическиеЛица.ДатаРождения В (ВЫБРАТЬ втПользователи.ДатаРождения ИЗ втПользователи)

А Можно и так:

ГДЕ (ФизическиеЛица.Код, ФизическиеЛица.Наименование, ФизическиеЛица.ДатаРождения) В (ВЫБРАТЬ втПользователи.Код, втПользователи.Наименование, втПользователи.ДатаРождения ИЗ втПользователи)

Причем обязателено соблюдать порядок.

16. Вызов конструктора запросов для "условия" в пакетном запросе

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

Необходимо после Конструкции "В" поставить скобки и между скобками оставить пустое место(пробел), выделить это место и вызвать контруктор запросов. Контруктору будут доступны все таблицы пакетного запроса. Прием работает как на виртуальных таблицах регистров, так и для вкладки "Условия". В последнем случае необходимо поставить галочку "П(произволное условие)" и войти в режим редактирования "F4".

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

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

upd1. Пункты 11,12
upd2. Пункты 13,14,15,16

Используемая литература:
Язык запросов "1С:Предприятия 8" - Е.Ю. Хрусталева
Профессиональная разработка в системе 1С:Предприятие 8".

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Результат:

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

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

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

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

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

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

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. Запрос с использованием функции КОЛИЧЕСТВО РАЗЛИЧНЫХ будет выглядеть так:

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

Результат:

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

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

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

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

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