Упорядочить по иерархия в запросе 1с
Примеры запросов для работы с иерархическими справочниками
В данном разделе показаны примеры решения типовых задач при работе с иерархическими справочниками.
Получение элементов иерархического справочника, находящихся в подчинении заданной группы
Для получения подчиненных элементов иерархического справочника в языке запросов предусмотрена конструкция В ИЕРАРХИИ. Пример использования В ИЕРАРХИИ:
ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Ссылка В ИЕРАРХИИ(&Группа)
В данном примере будут получены все записи справочника Номенклатура, находящиеся в группе &Группа, включая ее саму, ее подчиненные группы и элементы, принадлежащие подчиненным группам.
Если же нас интересуют только элементы и группы, находящиеся непосредственно в заданной группе, то такие элементы мы можем получить установив условие на поле Родитель. Пример:
ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Родитель = &Группа
Такой запрос выберет группы и элементы, находящиеся в подчинении группы со ссылкой &Группа.
Проверка наличия подчиненных элементов у элемента справочника
Для проверки наличия подчиненных записей элемента справочника можно пользоваться запросом, аналогичным представленному:
ВЫБРАТЬ ПЕРВЫЕ 1
Номенклатура.Ссылка
ИЗ
Справочник.Номенклатура КАК Номенклатура
ГДЕ
Номенклатура.Родитель = &Родитель
В данном примере ссылка элемента, для которого необходимо проверить наличие дочерних элементов, записывается в параметр запроса "Родитель". После выполнения такого запроса необходимо проверить результат на пустоту. Если результат не пустой, то подчиненные записи есть. Иначе - нет. Пример:
Если Запрос.Выполнить().Пустой() Тогда
Сообщить("Зписей нет");
Иначе
Сообщить("Записи есть");
КонецЕсли;
Получение всех родителей элемента
В языке запросов не предусмотрено специальных средств для получения всех родителей элемента. Для выполнения задачи можно воспользоваться иерархическими итогами, однако получение иерархических итогов оптимизировано для построения итогов большого количества записей, и не вполне эффективно для получения родителей одного элемента. Для более эффективного получения всех родительских записей элемента, рекомендуется перебирать в цикле его родителей небольшими порциями. Пример:
Запрос = Новый Запрос("ВЫБРАТЬ
| Номенклатура.Родитель,
| Номенклатура.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель.Родитель,
| Номенклатура.Родитель.Родитель.Родитель.Родитель.Родитель
|ИЗ
| Справочник.Номенклатура КАК Номенклатура
|
|ГДЕ
| Номенклатура.Ссылка = &ТекущийЭлементНоменклатуры";
Пока Истина Цикл
Запрос.УстановитьПараметр("ТекущийЭлементНоменклатуры", ТекущийЭлементНоменклатуры);
Результат = Запрос.Выполнить();
Если Результат.Пустой() Тогда
Прервать;
КонецЕсли;
Выборка = Результат.Выбрать();
Выборка.Следующий();
Для НомерКолонки = 0 По Результат.Колонки.Количество() - 1 Цикл
ТекущийЭлементНоменклатуры = Выборка[НомерКолонки];
Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
Прервать;
Иначе
Сообщить(ТекущийЭлементНоменклатуры);
КонецЕсли;
КонецЦикла;
Если ТекущийЭлементНоменклатуры = Справочники.Номенклатура.ПустаяСсылка() Тогда
Прервать;
КонецЕсли;
КонецЦикла;
Если число уровней в справочнике ограничено и невелико, то возможно получение всех родителей одним запросом без цикла.
Вывод иерархического справочника в отчет
Для вывода иерархического справочника в отчет с сохранением иерархии необходимо пользоваться запросом аналогичным следующему:
ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ
Справочник.Номенклатура КАК Номенклатура
УПОРЯДОЧИТЬ ПО
Наименование ИЕРАРХИЯ
Данный запрос выбирает все записи из справочника и производит упорядочивание по иерархии. Результат будет упорядочен по наименованию, с учетом иерархии.
Для того чтобы группы справочника размещались выше элементов необходимо в данном запросе заменить предложение УПОРЯДОЧИТЬ ПО на следующее:
УПОРЯДОЧИТЬ ПО
Номенклатура.ЭтоГруппа ИЕРАРХИЯ,
Наименование
Результат по-прежнему будет упорядочен по иерархии, однако группы будут располагаться выше элементов.
Возможна также замена предложения УПОРЯДОЧИТЬ ПО на предложение АВТОУПОРЯДОЧИВАНИЕ. В этом случае результат будет упорядочен в соответствии с настройками справочника, т.е. если в справочнике указано, что группы должны располагаться выше элементов, то они будут расположены выше.
Получить иерархическую структуру справочника также возможно и при помощи итогов.
ВЫБРАТЬ
Номенклатура.Код,
Номенклатура.Наименование КАК Наименование,
Номенклатура.ЗакупочнаяЦена
ИЗ Справочник.Номенклатура КАК Номенклатура
ГДЕ
(Номенклатура.ЭтоГруппа = ЛОЖЬ)
УПОРЯДОЧИТЬ ПО Наименование
ИТОГИ ПО Номенклатура.Ссылка ТОЛЬКО ИЕРАРХИЯ
Получение итогов по иерархии
Для получения итогов по иерархии в запросе необходимо в предложении ИТОГИ ПО указать ключевое слово ИЕРАРХИЯ после указания поля, по которому будет рассчитываться итоги. Пример отчета "Обороты номенклатуры" с получением итогов по иерархии:
ВЫБРАТЬ
УчетНоменклатурыОбороты.Номенклатура КАК Номенклатура,
УчетНоменклатурыОбороты.Номенклатура.Представление,
УчетНоменклатурыОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
РегистрНакопления.УчетНоменклатуры.Обороты КАК УчетНоменклатурыОбороты
ИТОГИ СУММА(КоличествоОборот) ПО
Номенклатура ИЕРАРХИЯ
В результате данного запроса будут рассчитаны итоги не только для каждой номенклатуры, но и для групп, к которым принадлежит та или иная номенклатура.
В случае, когда не нужны итоги по элементам, а нужны итоги только по группам, нам необходимо использовать в итогах конструкцию ТОЛЬКО ИЕРАРХИЯ. Пример:
ВЫБРАТЬ
УчетНоменклатурыОбороты.Номенклатура КАК Номенклатура,
УчетНоменклатурыОбороты.Номенклатура.Представление,
УчетНоменклатурыОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
РегистрНакопления.УчетНоменклатуры.Обороты КАК УчетНоменклатурыОбороты
ИТОГИ СУММА(КоличествоОборот) ПО
Номенклатура ТОЛЬКО ИЕРАРХИЯ
В результате данного запроса будут итоговые записи только для групп номенклатуры.
Войдите как ученик, чтобы получить доступ к материалам школы
Язык запросов 1С 8.3 для начинающих программистов: упорядочивание
Автор уроков и преподаватель школы: Владимир Милькин
Упорядочивание в запросах
Давайте напишем запрос, который получает из таблицы Справочник.Еда код и название еды:
Как всегда, выполните этот запрос у себя на компьютере.
С большой долей вероятности у вас получится следующий результат:
Возможно вы удивитесь, но при таком написании запроса никто не гарантирует нам именно такого порядка выдачи записей в таблице. В случае использования клиент-серверного режима работы на различных СУБД результат мог бы быть и такой:
И . ну в общем вы поняли, что если мы не указываем порядок сортировки (упорядочивания) результата запроса, то этот самый порядок может быть абсолютно любым.
Секция УПОРЯДОЧИТЬ ПО
Поля по которым требуется упорядочить запрос перечисляются в секции УПОРЯДОЧИТЬ ПО через запятую:
Следом за именем поля упорядочивания может идти одно из двух ключевых слов:
- ВОЗР- упорядочивание по возрастанию.
- УБЫВ - упорядочивание по убыванию.
Если не указывать ни одно из этих слов, считается, что сортировка идёт по возрастанию.
Вооружившись знаниями, давайте упорядочим результат нашего запроса по убыванию поля Код:
По возрастанию поля Наименование (алфавитный порядок):
А теперь упорядочим следующую таблицу
так, чтобы сначала шла сортировка по полю Вкус по возрастанию, а затем (среди строчек с одинаковым значением поля Вкус) шла сортировка по полю Цвет по убыванию:
Отдельно обращаю ваше внимание на то, что мы указали сортировку не по самим полям Вкус и Цвет, а по их строковому реквизиту Наименование. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Это связано с тем, что сортировка возможна лишь по полям имеющим один из типов: Строка, Число, Дата.
А поля Вкус и Цвет являются ссылками на элементы справочников Вкус и Цвет, сортировать по которым не имеет смысла (в этом случае сортировка будет вестись по внутреннему идентификатору ссылки). Зато можно сделать сортировку по одному из реквизитов этих элементов. Наиболее подходящим в нашем случае будет строковый реквизит Наименование.
Возможность автоупорядочивания
Ключевое слово АВТОУПОРЯДОЧИВАНИЕ позволяет включить режим автоматического формирования полей для упорядочивания результатов запроса.
Мы сейчас познакомимся с этой возможностью подробно, но сразу хочется оговориться, что фирма "1С" в своих методических рекомендациях не советует использовать её без необходимости (о причинах этого мы поговорим ниже).
Прежде всего, ключевое слово АВТОУПОРЯДОЧИВАНИЕ может быть расположено в запросе сразу за или вместо секции УПОРЯДОЧИТЬ ПО:
Автоупорядочивание работает по следующим принципам:
Тогда ссылка на каждую таблицу в этой секции будут заменена полями, по которым по умолчанию сортируется эта таблица.
Для таблиц справочников полями сортировки по умолчанию являются код и наименование, выбор из которых осуществляется в соответствии с настройками справочника в конфигураторе:
Для таблиц документов полем сортировки по умолчанию является дата документа.
Так как поле сортировки ЛюбимыйЦвет имеет тип Справочник.Цвета, в настройках которого основным представлением выбрано поле Наименование, то этот запрос эквивалентен:
- отсутствует секция УПОРЯДОЧИТЬ ПО
- но есть секция ИТОГИ ПО (её мы будем проходить позже)
В этом случае результат запроса будет упорядочен по полям итогов (в той же последовательности).
Если среди этих полей есть ссылки на таблицы, то они также будут заменены полями, по которым сортируются эти таблицы по умолчанию.
- отсутствует секция УПОРЯДОЧИТЬ ПО
- отсутствует секция ИТОГИ ПО
- но есть секция СГРУППИРОВАТЬ ПО (группировку мы проходили здесь)
В этом случае результат запроса будет упорядочен по полям группировки (в той же последовательности).
Если среди этих полей есть ссылки на таблицы, то они также будут заменены полями, по которым сортируются эти таблицы по умолчанию.
Так как поле группировки Город имеет тип Справочник.Города, в настройках которого основным представлением выбрано поле Наименование, то этот запрос эквивалентен:
Наконец, если в запросе:
- отсутствует секция УПОРЯДОЧИТЬ ПО
- отсутствует секция ИТОГИ ПО
- отсутствует секция СГРУППИРОВАТЬ ПО
В этом случае результат запроса будет упорядочен по полям сортировки по умолчанию для таблиц, из которых выбираются данные, в порядке их появления в запросе.
Так как данные выбираются из справочника Еда, в настройках которого основным представлением выбрано поле Наименование, то этот запрос будет эквивалентен:
Почему использование автоупорядочивания нежелательно
- для универсальных запросов, когда разработчик не может предвидеть из каких таблиц будут запрашиваться данные
- для случаев, когда получаемый порядок записей не важен, но при этом он должен быть одинаковым в независимости от применяемой СУБД
Во всех остальных случаях использовать возможность автоупорядочивания нежелательно, так как поля, которые являются полями сортировки сегодня, могут перестать быть такими завтра.
Например, сегодня мы можем написать код, чувствительный к тому, чтобы результаты запроса из справочника Еда были отсортированы по полю Наименование.
А завтра фирма "1С" (или другой разработчик) изменят настройки базы в конфигураторе так, что полем сортировки по умолчанию для справочника Еда станет, к примеру, поле Код. И, если мы использовали автоупорядочивание в запросе, то наш отчет сломается, ведь порядок сортировки уже будет другим. Вы читаете ознакомительную версию урока, полноценные уроки находятся здесь.
Поэтому всегда старайтесь указывать конкретные поля и конкретный порядок сортировки по ним в секции УПОРЯДОЧИТЬ ПО, такой запрос уже не сломать просто так:
&НаСервере
Процедура УпорядочиваниеРезультатаЗапросаПоОпределеннымПолям ()
// Выборка материалов, упорядоченных сперва по возрастанию срока использования,
// а потом по убыванию веса
Запрос = Новый Запрос ( "ВЫБРАТЬ
| Наименование,
| СрокИспользования,
| Вес
|ИЗ
| Справочник.Материалы
|УПОРЯДОЧИТЬ ПО
| СрокИспользования ВОЗР,
| Вес УБЫВ" );
РезультатЗапроса = Запрос . Выполнить (); Записи = РезультатЗапроса . Выбрать ();
Пока Записи . Следующий () Цикл
// Обход результата запроса по каждой записи в полученной выборке
КонецЦикла;
&НаСервере
Процедура УпорядочиваниеРезультатаЗапросаПоИерархии ()
// Выборка контрагентов в порядке их следования в иерархии
Запрос = Новый Запрос ( "ВЫБРАТЬ
| Наименование
|ИЗ
| Справочник.Контрагенты КАК Производитель
|УПОРЯДОЧИТЬ ПО
| Наименование Иерархия" );
РезультатЗапроса = Запрос . Выполнить (); Записи = РезультатЗапроса . Выбрать ();
Пока Записи . Следующий () Цикл
// Обход результата запроса по каждой записи в полученной выборке
КонецЦикла;
&НаСервере
Процедура УпорядочиваниеРезультатаЗапросаПоВыражению ()
// Выборка материалов, упорядоченных сперва по убыванию максимальной фасовке и плотности вместе
Запрос = Новый Запрос ( "ВЫБРАТЬ
| Наименование,
| Фасовка,
| Плотность
|ИЗ
| Справочник.Материалы
|УПОРЯДОЧИТЬ ПО
| (Фасовка + Плотность) УБЫВ" );
РезультатЗапроса = Запрос . Выполнить (); Записи = РезультатЗапроса . Выбрать ();
Пока Записи . Следующий () Цикл
// Обход результата запроса по каждой записи в полученной выборке
КонецЦикла;
&НаСервере
Процедура УпорядочиваниеРезультатаЗапросаПоАгрегатнойФункцииГруппировки ()
// Выборка материалов с минимальным весом и группировкой по сроку использования
// Запрос отсортируем по минимальному весу
Запрос = Новый Запрос ( "ВЫБРАТЬ
| СрокИспользования,
| МИНИМУМ(Вес)
|ИЗ
| Справочник.Материалы
|СГРУППИРОВАТЬ ПО
| СрокИспользования
|УПОРЯДОЧИТЬ ПО
| МИНИМУМ(Вес) ВОЗР" );
РезультатЗапроса = Запрос . Выполнить (); Записи = РезультатЗапроса . Выбрать ();
Пока Записи . Следующий () Цикл
// Обход результата запроса по каждой записи в полученной выборке
КонецЦикла;
&НаСервере
Процедура АвтоупорядочиваниеРезультатаЗапроса ()
// Сортировка по полю Ссылка и использование ключевого слова АВТОУПОРЯДОЧИВАНИЕ. При этом
// поле Ссылка в секции УПОРЯДОЧИТЬ ПО будет автоматически изменена на дату документа.
Запрос = Новый Запрос ( "ВЫБРАТЬ
| ПоступлениеМатериалов.Ссылка
|ИЗ
| Документ.ПоступлениеМатериалов КАК ПоступлениеМатериалов
|УПОРЯДОЧИТЬ ПО
| ПоступлениеМатериалов.Ссылка
|АВТОУПОРЯДОЧИВАНИЕ" );
РезультатЗапроса = Запрос . Выполнить (); Записи = РезультатЗапроса . Выбрать ();
Пока Записи . Следующий () Цикл
// Обход результата запроса по каждой записи в полученной выборке
КонецЦикла;
Читайте также: