Основные приемы работы
Основные приемы работы
Общее [#Common]
Способы обхода результата запроса [#WorkaroundType]
Линейный обход результата [#LinearlWorkaround]
Иерархический обход результата [#HierarchicalWorkaround]
Обход результата по группам [#GroupWorkaround]
Работа с выборкой [#WorkWithSelection]
Методы определения типа текущей записи [#CurRecordTypeMethods]
Основные приемы работы с запросами во встроенном языке 1С:Предприятия удобнее всего рассматривать на примерах. Приведем типичный пример использования запроса:
Запрос = Новый Запрос("ВЫБРАТЬ Товар.Наименование Наименование,
|Товар.Родитель.Наименование НаименованиеРодителя
|ИЗ Справочник.Товары Товар");
// Выполним запрос и запишем результат в переменную РезультатЗапроса.
РезультатЗапроса = Запрос.Выполнить();
// Получим выборку из результата запроса.
Выборка = РезультатЗапроса.Выбрать();
// Пока в выборке есть записи ...
Пока Выборка.Следующий() Цикл
// ... выведем в окно сообщений поля из результата.
Товар = Выборка.Наименование;
Родитель = Выборка.НаименованиеРодителя;
Сообщить("Товар: " + Товар + " Родитель: " + Родитель);
КонецЦикла;
Как видно из этого примера, работа с запросом ведется при помощи трех основных объектов:
- Запрос – объект, выполняющий сам запрос. Представлен в примере переменной с именем Запрос.
- РезультатЗапроса – объект, содержащий полученные при выполнении запроса данные. Представлен в примере переменной с именем РезультатЗапроса.
- ВыборкаИзРезультатаЗапроса [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection.html] – объект, позволяющий обходить (т.е. перебрать) записи из результата. Представлен в примере переменной с именем Выборка.
Рассмотрим подробнее объект ВыборкаИзРезультатаЗапроса [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection.html]. Для этого нам понадобится следующий текст запроса:
ВЫБРАТЬ
Товар, Количество
ИЗ
Документ.РасхНакл.Состав
УПОРЯДОЧИТЬ ПО Товар
ИТОГИ Сумма(Количество) ПО Товар Иерархия
Его результат представлен в таблице:
N
Товар
Количество
1
Сантехника
104
2
Кран
84
3
Кран
10
4
Кран
8
5
Кран
44
6
Кран
22
7
Смеситель
20
8
Смеситель
5
9
Смеситель
1
10
Смеситель
14
11
Мебель
134
12
Стол
26
13
Стол
1
14
Стол
15
15
Стол
10
16
Стул
108
17
Стул
55
18
Стул
5
19
Стул
32
20
Стул
16
В эту таблицу добавлена колонка "N", которой нет в результате запроса, но которая будет использоваться нами в дальнейшем для идентификации записи в результате. Итоговые записи в таблице выделены курсивом, итоговые записи для иерархических уровней справочника выделены полужирным шрифтом.
Способы обхода результата запроса
Линейный обход результата
Первый, и самый простой способ обхода – линейный. При линейном обходе выборка будет выдавать записи в той последовательности, в которой они располагаются в результате запроса. В нашем примере это будут записи с номерами 1, 2, 3, 4, 5 и так далее до записи с номером 20.
Для получения линейной выборки из результата необходимо вызвать метод Выбрать объекта РезультатЗапроса без параметров, либо с параметром ОбходРезультатаЗапроса [v8help://SyntaxHelperContext/objects/catalog2/catalog259/QueryResultIteration.html].Прямой [v8help://SyntaxHelperContext/objects/catalog2/catalog259/QueryResultIteration/properties/Linear1013.html].
Пример:
СпособВыборки = ОбходРезультатаЗапроса.Прямой;
Выборка1 = РезультатЗапроса.Выбрать(СпособВыборки);
// что равнозначно записи
Выборка1 = РезультатЗапроса.Выбрать();
Иерархический обход результата
Следующий способ обхода результата – иерархический. При данном обходе обходятся только записи, находящиеся на одном уровне. Для получения иерархической выборки из результата необходимо вызвать метод Выбрать() объекта РезультатЗапроса с параметром ОбходРезультатаЗапроса [v8help://SyntaxHelperContext/objects/catalog2/catalog259/QueryResultIteration.html].ПоГруппировкамСИерархией [v8help://SyntaxHelperContext/objects/catalog2/catalog259/QueryResultIteration/properties/ByGroupsWithHierarchy1015.html].
Пример:
СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
Выборка2 = РезультатЗапроса.Выбрать(СпособВыборки);
Выборка из результата с иерархическим обходом в нашем примере обойдет только записи с номерами 1 и 11, так как только эти две записи находятся на самом верхнем уровне. Проиллюстрируем это, представив наш результат в виде дерева, где узлами будут итоговые записи, а листьями дерева будут детальные записи. Вот что у нас получится:
Из этого рисунка видно, что именно записи с номерами 1 и 11, и только они находятся на первом уровне дерева, в результате чего только они и попадают в первый проход иерархической выборки.
Возникает вопрос, как получать остальные записи результата запроса. Для этого у объекта ВыборкаИзРезультатаЗапроса [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection.html] можно получить еще одну выборку, которая будет обходить подчиненные записи текущей записи выборки. В нашем примере в момент, когда объект Выборка2 будет позиционирован на запись с номером 1, мы запросим у него иерархическую выборку. Таким образом, мы получим выборку, которая нам вернет записи с номерами 2, 7. А когда Выборка2 будет спозиционирована на записи с номером 11, то полученная у нее иерархическая выборка вернет записи с номерами 12, 16. Так реализуется иерархический обход результатов запроса. Заметим, что у выборки можно получать вложенные выборки любого типа. Так, если бы мы запросили у Выборки2, спозиционированной на записи 1, линейную выборку, то с ее помощью мы бы получили записи с номерами записей со 2-го по 10-й. Проиллюстрируем описанную методику на примере.
Пример:
Процедура ВыполнитьЗапрос()
// Создадим запрос.
Запрос = Новый Запрос;
// Установим текст запроса
Запрос.Текст = "ВЫБРАТЬ
|Товар, Количество
|ИЗ
|Документ.РасхНакл.Состав
|УПОРЯДОЧИТЬ ПО Товар
|ИТОГИ Сумма(Количество) ПО Товар, Товар Иерархия";
// Выполним запрос и запишем результат в переменную
// РезультатЗапроса.
РезультатЗапроса = Запрос.Выполнить();
// Получим выборку из результата запроса.
СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
Выборка = РезультатЗапроса.Выбрать(СпособВыборки);
ВыдатьРекурсивно(Выборка);
КонецПроцедуры
Процедура ВыдатьРекурсивно(Выборка)
// Пока в выборке есть записи ...
Пока Выборка.Следующий() Цикл
// ... выведем в окно сообщений поля из результата
Товар = Выборка.Наименование;
Количество = Выборка.Количество;
Сообщить("Товар: " + Товар + " Количество: " + Количество);
// Продолжим выборку подчиненных записей
СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
Если Выборка.ТипЗаписи() = ТипЗаписиЗапроса.ИтогПоИерархии Тогда
ДочерняяВыборка = Выборка.Выбрать(СпособВыборки, Выборка.Группировка());
Иначе
ДочерняяВыборка = Выборка.Выбрать(СпособВыборки);
КонецЕсли;
ВыдатьРекурсивно(ДочерняяВыборка);
КонецЦикла;
КонецПроцедуры
Обход результата по группам
Третий, и последний способ обхода результата – по группам. Он сходен с иерархическим обходом, но с одним различием: записи с иерархическими итогами при обходе в нем рассматриваются как детальные записи, а не как узловые. Для получения выборки по группам из результата запроса необходимо вызвать метод Выбрать объекта РезультатЗапроса с параметром ОбходРезультатаЗапроса.ПоГруппировкам.
Пример:
СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкам;
Выборка2 = РезультатЗапроса.Выбрать(СпособВыборки);
Перебрав в ней всё, мы получим записи с номерами 1, 2, 7, 11, 12, 16.
Пример:
Процедура ВыполнитьЗапрос()
// Создадим запрос.
Запрос = Новый Запрос;
// Установим текст запроса
Запрос.Текст = "ВЫБРАТЬ
|Товар, Количество
|ИЗ
|Документ.РасхНакл.Состав
|УПОРЯДОЧИТЬ ПО Товар
|ИТОГИ Сумма(Количество) ПО Товар, Товар Иерархия";
// Выполним запрос и запишем результат в переменную
// РезультатЗапроса.
РезультатЗапроса = Запрос.Выполнить();
// Получим выборку из результата запроса
СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкам;
Выборка = РезультатЗапроса.Выбрать(СпособВыборки);
// Пока в выборке есть записи ...
Пока Выборка.Следующий() Цикл
// ... выведем в окно сообщений поля из результата
Товар = Выборка.Наименование;
Количество = Выборка.Количество;
Сообщить("Товар: "+Товар+" Итого по товару: "+Количество);
ВыдатьДочерниеЗаписи(Выборка.Выбрать());
КонецЦикла;
КонецПроцедуры
Процедура ВыдатьДочерниеЗаписи (Выборка)
// Пока в выборке есть записи ...
Пока Выборка.Следующий() Цикл
// ... выведем в окно сообщений поля из результата
Товар = Выборка.Наименование;
Количество = Выборка.Количество;
Сообщить("Товар: "+Товар+" Количество: "+Количество);
КонецЦикла;
КонецПроцедуры
Работа с выборкой
Объект ВыборкаИзРезультатаЗапроса [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection.html] предназначен для обхода записей результата запроса. Можно представить себе выборку как некоторый объект, который содержит указатель на текущую запись в результате и предоставляет программе доступ ко всем полям текущей записи. Для навигации по записям запроса используются три метода:
- Следующий() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/Next556.html] – перейти к следующей записи результата в соответствии с порядком обхода выборки. При первом вызове позиционирует выборку на первую запись. Когда будут выбраны все записи, данный метод просигнализирует об этом, вернув значение Ложь [v8help://SyntaxHelperLanguage/def_BooleanFalse].
- СледующийПоЗначениюПоля() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/NextByFieldValue594.html] – получить следующую запись со значением в заданном поле, отличающимся от значения в этом поле текущей записи.
- НайтиСледующий () [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/FindNext595.html] – найти запись, с заданными значениями некоторых полей.
Использование метода СледующийПоЗначениюПоля
Метод позволяет сгруппировать записи результата по значениям полей.
Пример запроса:
ВЫБРАТЬ
Док.Товар, Док.Получатель, Док.Количество
ИЗ
Документ.РасхНакл.Состав Док
УПОРЯДОЧИТЬ ПО Док.Товар.Наименование, Док.Получатель.Наименование
Его результат:
N
Товар
Получатель
Количество
1
Смеситель
Маг. "Гигант"
14
2
Смеситель
Маг. "Хозяин"
1
3
Смеситель
Мосгорторг
5
4
Кран
Маг. "Гигант"
44
5
Кран
Маг. "Хозяин"
8
6
Кран
Мосгорторг
10
7
Кран
Мосгорторг
22
8
Стол
Маг. "Гигант"
10
9
Стол
Маг. "Мебель"
15
10
Стол
Мосгорторг
1
11
Стул
Маг. "Гигант"
32
12
Стул
Маг. "Мебель"
55
13
Стул
Маг. "Хозяин"
5
14
Стул
Мосгорторг
16
Получим линейную выборку из результата запроса и обойдем выборку при помощи метода СледующийПоЗначениюПоля.
Пример:
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.СледующийПоЗначениюПоля("Товар") Цикл
// здесь мы получим записи с номерами 1, 4, 8, 11
Пока Выборка.СледующийПоЗначениюПоля("Получатель") Цикл
// здесь мы сначала получим записи с номерами 1, 2, 3
// затем 4, 5, 6
// затем 8, 9, 10
// затем 11, 12, 13, 14
КонецЦикла;
КонецЦикла;
Следует обратить внимание на то, что во внутреннем цикле не была выбрана запись с номером 7, т.к. в ней такое же значение поля "Получатель" как и в предыдущей записи.
Заметим, что если в цикле получения по значению поля получать записи при помощи метода Следующий() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/Next556.html], то будут выбраны все записи с равным значением поля, заданного в предыдущем вызове метода СледующийПоЗначениюПоля() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/NextByFieldValue594.html].
Пример:
Выборка = РезультатЗапроса.Выбрать();
Пока Выборка.СледующийПоЗначениюПоля("Товар") Цикл
// здесь мы получим записи с номерами 1, 4, 8, 11
Пока Выборка.Следующий() Цикл
// здесь мы сначала получим записи с номерами 1, 2, 3
// затем 4, 5, 6, 7
// затем 8, 9, 10
// затем 11, 12, 13, 14
КонецЦикла;
КонецЦикла;
Методы определения типа текущей записи
В тот момент, когда выборка позиционирована на записи, мы можем у выборки узнать характеристики этой записи. Получение характеристик записи осуществляется методами:
- Уровень() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/Level558.html] – определяет уровень записи в результате запроса.
- ТипЗаписи() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/RecordType559.html] – определяет принадлежность записи к одному из следующих типов:
- групповой итог;
- итого по иерархии;
- детальная запись;
- общий итог.
- Группировка() [v8help://SyntaxHelperContext/objects/catalog213/catalog393/QueryResultSelection/methods/Group560.html] – определяет имя поля, по которому были рассчитаны итоги.
Для иллюстрации работы этих методов посмотрим, что они будут возвращать записей для запроса, рассматриваемого в начале главы:
ВЫБРАТЬ
Товар, Количество Количество
ИЗ
Документ.РасхНакл.Состав
УПОРЯДОЧИТЬ ПО Товар
ИТОГИ Сумма(Количество) ПО Товар, Товар Иерархия
Результат представлен в таблице:
N
Товар
Количество
Уровень
ТипЗаписи
Группировка
1
Сантехника
104
0
ИтогПоИерархии
Товар
2
Кран
84
1
ИтогПоГруппировке
Товар
3
Кран
10
2
ДетальнаяЗапись
4
Кран
8
2
ДетальнаяЗапись
5
Кран
44
2
ДетальнаяЗапись
6
Кран
22
2
ДетальнаяЗапись
7
Смеситель
20
1
ИтогПоГруппировке
Товар
8
Смеситель
5
2
ДетальнаяЗапись
9
Смеситель
1
2
ДетальнаяЗапись
10
Смеситель
14
2
ДетальнаяЗапись
11
Мебель
134
0
ИтогПоИерархии
Товар
12
Стол
26
1
ИтогПоГруппировке
Товар
13
Стол
1
2
ДетальнаяЗапись
14
Стол
15
2
ДетальнаяЗапись
15
Стол
10
2
ДетальнаяЗапись
16
Стул
108
1
ИтогПоГруппировке
Товар
17
Стул
55
2
ДетальнаяЗапись
18
Стул
5
2
ДетальнаяЗапись
19
Стул
32
2
ДетальнаяЗапись
20
Стул
16
2
ДетальнаяЗапись