| Петров
| |
| | 2003
| | | | Февраль
| | | | 12000
|
| В следующем примере эта таблица сворачивается по колонкам Сотрудник и Год с подсчетом суммы по колонке Доход:
| |
| //подсчитаем годовой доход по каждому сотруднику
| |
| тзДоходыСотр.Свернуть("Сотрудник,Год","Доход");
| |
| В результате мы получим следующую таблицу значений:
| |
| Иванов
| | 2003
| | 29000
| |
Петров
| | 2003
| | 27000
| |
| Если исходная таблица значений вам понадобится в дальнейшем, то лучше сделать копию таблицы значений и сворачивать уже ее:
| |
| тзДоходыПоГодам = тзДоходыСотр.Скопировать();
| |
| тзДоходыПоГодам.Свернуть("Сотрудник,Год","Доход");
| |
| Таблица значений позволяет подсчитать итог по колонке числового типа, например:
| |
| ВсегоДоход = тзДоходыСотр.Итог("Доход");
| |
| ВсегоНДС = тзСостав.Итог("НДС");
| |
| И последнее, о чем хотелось рассказать, из таблицы значений можно выгрузить целую колонку в массив и загрузить ее из массива:
| |
| МассивЦен = тзТовары. ВыгрузитьКолонку ("Цена") ;
| |
| тзТовары.ЗагрузитьКолонку("Количество",МассивОстаткиТоваров);
| |
Код:
Маc= Новый Массив; //одномерный массив без элементов
Мас2 = Новый Массив(10); //одномерный массив из 10 элементов
Мас3 = Новый Массив(4,5); //массив с двумя измерениями
| При указании нескольких параметров конструктора фактически создается массив, элементами которого являются другие массивы, что является аналогом многомерного массива. Для добавления и удаления элементов массива можно использовать методы объекта Массив:
| |
Маc = Новый Массив; //одномерный массив без элементов
Маc.Добавить("Иванов"); //элемент будет иметь индекс 0
Маc.Добавить("Петров"); //индекс 1
Маc.Добавить("Сидоров"); //индекс 2
//после вставки нового элемента Иванов и Петров будут сдвинуты ниже
Мас2.Вставить(0,"Сидоров");
//удаляем Сидорова (Иванов и Петров сдвигаются обратно)
Мас2.Удалить(0);
Мас2 = Новый Массив(4,5); //массив с двумя измерениями
Мас2[0][0] = "Иванов";
Мас2[0][1] = "Петров";
//после вставки нового элемента Иванов и Петров будут сдвинуты ниже
Мас2[0].Вставить(0,"Сидоров");
//следующий элемент будет относиться ко 2-му измерению
//и будет являться 6-м (индекс = 5)
//при создании массива во 2-м измерении
//было создано 5 элементов, имеющих значение Неопределено
Мас2[1].Добавить("Петров");
| Перебор элементов массива возможен с использованием операто-ра [...] или цикла «Для Каждого»:
| |
//1-йвариант
Для Каждого эл Из Мас Цикл
КонецЦикла;
//2-й вариант
Для н = 0 По Мас.ВГраница() Цикл
КонецЦикла;
| У объекта Массив есть следующие методы:
| |
Отбор= Новый Структура("Цена", 100);
Выборка = Справочники.Номенклатура . Выбрать (,Отбор);
| Структуры можно использовать для передачи списка параметров (в версии 7.7 для этой цели часто применялся список значений и его методы Установить и Получить):
| |
Параметры = Новый Структура("ДатаНач,ДатаКон");
Параметры.ДатаНач = ВыбДата;
Параметры.ДатаКон = ДобавитьМесяц(ВыбДата,1);
Если ВыбТипОтчета <> 0 Тогда
| Параметры.Вставить("ТипОтчета",ВыбТипОтчета);
| |
КонецЕсли;
глСформироватьОбороты(Параметры);
| Можно перебрать элементы структуры или соответствия с помощью конструкции «Для Каждого». Каждый элемент коллекции является объектом специального типа КлючИЗначение:
| |
ДляКаждого парам Из Параметры Цикл
| ИмяПараметра = парам.Ключ;
| |
| Значение = парам.Значение;
| |
КонецЦикла;
| Для структуры можно обращаться к элементам коллекции через точку, поскольку ключи являются свойствами структуры:
| |
НачДата = парам.ДатаНач;
КонДата = парам.ДатаКон;
| Для соответствия такое обращение через точку невозможно, так как ключи соответствия могут быть самого разнообразного типа. С помощью метода Свойство можно получить значение заданного ключа или убедиться, что его в структуре нет,
| |
ТоварАналог = соотвАналоги[Товар].Значение;
сзСотр= Новый СписокЗначений;
| Ниже демонстрируются приемы добавления и удаления элементов списка значений:
| |
сзСотр. Очистить(); //удалим все элементы
//У следующего элемента индекс 0, представление "Иванов Иван"
сзСотр.Добавить("Иванов","Иванов Иван");
//У следующего элемента будет индекс 1, представление "Петров Петр"
//и установлена пометка
сзСотр.Добавить("Петров","Петров Петр", Истина);
сзСотр.Удалить(1); //удалить 2-й элемент, т.е. Петрова
сзСотр.Вставить(0,"Сидоров"); //Иванов сдвигается ниже
сзСотр.Сдвинуть(1,-1); //сдвинем Иванова обратно к началу
| Обращение к элементу списка значений производится по индексу через оператор [...] или с помощью метода Получить,
| |
//1-й вариант
Для Каждого эл Из сзСотр Цикл
КонецЦикла;
//2-й вариант
Для н = 0 По сзСотр.Количество()-1 Цикл
| Сообщить(сзСотр[н].Значение);
| |
КонецЦикла;
| В списке значений можно искать заданное значение:
| |
НайденныйЭлементСписка= сзСотр.НайтиПоЗначению("Иванов");
Если НайденныйЭлементСписка <> Неопределено Тогда
| Сообщить("Элемент найден!");
| |
КонецЕсли;
| Как уже говорилось выше, в списке значений могут быть пометки, которые представляют собой флажки (значения типа «булево»). С помощью пометок несколько значений списка могут быть выделены, и тем самым они будут отличаться от остальных. Назначение пометок определяется проектной логикой. Разработчик может программно считывать и устанавливать пометки у элементов списка значений:
| |
сзСотр = Новый СписокЗначений;
сзСотр.Добавить("Иванов",,Истина);//пометка установлена
сзСотр.Добавить("Петров");//пометка не установлена
сзСотр.Добавить("Сидоров");//пометка не установлена
ВыборПроизведен = сзСотр.ОтметитьЭлементы("Укажите сотрудников");
Если ВыборПроизведен Тогда
| Для Каждого эл Из сзСотр Цикл
| |
| Сообщить("Отмечен сотрудник " + эл.Значение);
| |
КонецЕсли;
| Методы ВыбратьЭлемент и ОтметитьЭлементы открывают диалоговое окно для пользователя, в котором он может выбрать один элемент или расставить пометки, тем самым выбрав несколько элементов.
| |
| Элементы списка значений могут быть легко отсортированы по значению или по представлению:
| |
сзСотр.СортироватьПоЗначению(НаправлениеСортировки.Возр);
сзСотр.СортироватьПоПредставлению(НаправлениеСортировки.Убыв);
| В список значений можно загрузить значения из массива и выгрузить значения в массив, например:
| |
мас = Новый Массив;
мас.Добавить("Иванов");
мас.Добавить("Якушин");
мас.Добавить("Сидоров"};
сзСотр.ЗагрузитьЗначения(мас);
сзСотр.СортироватьПоЗначению();
мас2 = сзСотр.ВыгрузитьЗначения();
| При размещении в форме поля списка автоматически создается новый реквизит формы типа СписокЗначений. Через этот реквизит можно управлять содержимым списка, добавлять или удалять элементы, расставлять пометки, задавать картинки. Следует понимать, что ПолеСписка ? это не список значений, а элемент управления, имеющий собственный набор свойств и методов. Со списком значений также тесно связан элемент управления ПолеВыбора. Его свойство СписокВыбора представляет собой список значений, из которого пользователь может выбрать одно значение.
| |
тзТовары= Новый ТаблицаЗначений;
тзТовары.Колонки.Добавить("Ссылка");
тзТовары.Колонки.Добавить("Наименование");
тзТовары.Колонки.Добавить("Цена");
тзТовары.Колонки.Добавить("Количество");
| У таблицы значений есть свойство Колонки, которое представляет собой коллекцию колонок и позволяет добавлять, удалять и менять их порядок.
| |
| По умолчанию в таблице значений могут храниться значения разных типов. Но в 1С:Предприятии 8.0 для колонки можно задать список возможных типов значений. Это делается следующим образом (для повышения наглядности нам понадобится вспомогательная функция СоздатьОписаниеТипов):
| |
Функция СоздатьОписаниеТипов(НазваниеТипа,Длина,Точность="")
мас = Новый Массив;
мас.Добавить(Тип(НазваниеТипа));
| КвалифСтроки = Новый КвалификаторыСтроки(Длина,
| |
| ДопустимаяДлина.Переменная);
| |
| КвалифЧисла = Новый КвалификаторыЧисла(ДопустимыйЗнак.Любой,
| |
| Возврат Новый ОписаниеТипов(мас,КвалифСтроки,КвалифЧисла);
| |
КонецФункции
тзТовары = Новый ТаблицаЗначений;
ТипКолСсылка=СоздатьОписаниеТипов("СправочникСписок.Номенклатура");
тзТовары.Колонки.Добавить("Ссылка", ТипКолСсылка,"Товар",5);
ТипКолНаим=СоздатьОписаниеТипов("Строка",50);
тзТовары.Колонки.Добавить("Наименование", ТипКолНаим);
ТипКолЦена = СоздатьОписаниеТипов("Строка",15,2);
тзТовары.Колонки.Добавить("Цена", ТипКолЦена, "Цена",15);
ТипКолКолич = СоздатьОписаниеТипов("Строка",15,4);
тзТовары.Колонки.Добавить("Количество",ТипКолКолич,"Кол-во",15);
| При работе со строками таблицы значений необходимо понимать, что строка ? это объект типа СтрокаТаблицыЗначений. Поэтому добавление строк в таблицу значений производится следующим образом:
| |
//удаляемвсе строки из таблицы (колонки остаются)
тзТовары.Очистить();
СпрВыборка = Справочники.Номенклатура.Выбрать();
Пока СпрВыборка.Следующий() Цикл
тзТовары.Колонки.Очистить();
| По индексу можно удалить строку:
| |
тзТовары.Удалить(0);//удалить 1-ю строку с индексом 0
тзТовары.Удалить(1); //удалить 2-ю строку с индексом 1
| Перебор строк таблицы значений обычно реализуется с помощью конструкции «Для Каждого», при этом в переменной цикла будет содержаться не номер строки, а вся строка целиком как объект СтрокаТаблицыЗначений:
| |
Для Каждого стр Из тзТовары Цикл
| Сообщить(стр.Наименование);
| |
КонецЦикла;
| Допускается также обращение к строке по индексу, при этом так-же возвращается объект типа СтрокаТаблицыЗначений. При работе с индексами необходимо всегда помнить, что индексация строк таблицы значений начинается с 0.
| |
Длян=0 По тзТовары.Количество()-1 Цикл
| Сообщить(тзТовары[н].Наименование);
| |
| Сообщить(тзТовары[н].Цена);
| |
КонецЦикла;
| Часто возникает необходимость найти значение в таблице значений. Для решения этой задачи предназначены методы Найти и НайтиСтроки. В метод Найти передается искомое значение и список колонок, которые нужно просматривать. Если значение найдено, то возвращается строка таблицы значений, иначе ? значение Неопределено.
| |
НайденнаяСтрока = тзТовары.Найти(100,"Цена");
Если НайденнаяСтрока <> Неопределено Тогда
| Сообщить("Товар с такой ценой найден! " + НайденнаяСтрока.Наименование);
| |
КонецЕсли;
| Метод НайтиСтроки позволяет найти сразу несколько строк таблицы значений, удовлетворяющих заданному условию. В параметрах этого метода передается структура, задающая условия отбора. Ключ структуры определяет имя колонки, а ее значение ?искомое значение. Метод НайтиСтроки возвращает массив, содержащий ссылки на найденные строки таблицы значений:
| |
Отбор= Новый Структура("Цена",100);
МассивСтрок = тзТовары.НайтиСтроки(Отбор);
Сообщить("Найдено " + МассивСтрок.Количество() + " товаров с такой ценой");
тзТовары.Сортировать("НаименованиеВозр");
тзТовары.Сортировать("Цена Убыв");
тзТовары.Сортировать("Цена Убыв, Наименование Возр"););
| Таблица значений имеет очень полезную возможность группировки строк и подсчета итогов по группе, что реализуется методом Свернуть, имеющим следующие параметры:
| |
Свернуть(<Колонки группировок>, <Колонки суммирования>)
| Этот метод осуществляет свертку таблицы значений по указанным колонкам группировки. Строки, у которых совпадают значения в колонках, указанных в первом параметре, сворачиваются в одну строку. Значения по этим строкам, хранящиеся в колонках, указанных во втором параметре, суммируются.
| |
дзОтделы= Новый ДеревоЗначений;
дзОтделы.Колонки.Добавить("Отдел");
дзОтделы.Колонки.Добавить("Руководитель");
Нов = дзОтделы.Строки.Добавить(); //индекс 0
Нов.Отдел = "Бухгалтерия";
Нов = дзОтделы.Строки.Добавить(); //индекс 1
Нов.Отдел = "Руководство";
//детализируем отдел "Бухгалтерия"
Нов = дзОтделы.Строки[0] .Строки.Добавить();
Нов.Отдел = "Расчет зарплаты";
Нов = дзОтделы.Строки[0].Строки.Добавить();
Нов.Отдел = "Основные средства";
//детализируем руководство
Нов = дзОтделы.Строки[1] .Строки.Добавить();
Нов.Отдел = "Высшее руководство";
Нов = дзОтделы.Строки[1].Строки.Добавить();
Нов.Отдел = "Отдел маркетинга";
| Так же, как и с таблицей значений, можно создать полную копию дерева значений с помощью метода Скопировать:
| |
НоваяОргСтруктура = ДзОтделы.Скопировать();
| Обход строк реализуется с помощью конструкции «Для Каждого» или оператором [...]:
| |
//1-йвариант: обход строк 1-го уровня
Для Каждого стр Из дзОтделы Цикл
КснецЦикла;
//2-й вариант (индексация строк начинается с 0)
Для н = 0 По дзОтделы.Строки.Количество()-1 Цикл
| стр = дзОтделы.Строки[н];
| |
КснецЦикла;
| Следующая программа с помощью рекурсивной процедуры обходит все строки дерева значений, включая подчиненные:
| |
Процедура ПоказатьПодчиненные (СтрокаДерева,Уровень=0)
| Для Каждого стр Из СтрокаДерева.Строки Цикл
| |
| Для н = 1 По Уровень Цикл
| |
| Сообщить(отступ + стр.Отдел);
| |
| ПоказатьПодчиненные(стр,Уровень+1);
| |
КонецПроцедуры
ПоказатьПодчиненные(дзОтделы);
| Результат работы программы:
| |
Бухгалтерия
Руководство
| Аналогично таблице значений, дерево значений позволяет искать значение с помощью метода Найти или искать сразу несколько строк методом НайтиСтроки. Принципы работы этих методов полностью идентичны рассмотренным выше для таблицы значений, за исключением последнего параметра ВключатьПодчиненные. Если передать в него значение Истина, то поиск будет производиться в том числе и по подчиненным строкам, иначе ?только по строкам текущего уровня.
| |
Например:
Найдено= парам.Свойство("ТипОтчета",ВыбТипОтчета);
Если Найдено Тогда
| СформироватьПользовательскийОтчет(ВыбТипОтчета);
| |
Иначе
| СформироватьОтчетПоУмолчанию();
| |
КонецЕсли;
| У соответствия нет метода Свойство и обращение производится с помощью оператора [...] или метода Получить:
| |
сзСотр[0].Значение= "Кузнецов";
| Перебор элементов списка значений производится следующим образом:
| |
Очистить
Удаляет все значения из массива.
| В 1С:Предприятии 8.0 в массив можно загружать данные или выгружать данные из него в другие коллекции значений. Это реализуется с помощью соответствующих методов других коллекций значений. Например, объект СписокЗначений имеет методы ВыгрузитьЗначения и ЗагрузитьЗначения, которые работают с массивом. Аналогично действуют методы ВыгрузитьКолонку и ЗагрузитьКолонку объекта ТаблицаЗначений.
| |
Удалить
Удаляет значение из массива по указанному индексу.
ВГраница
Возвращает наибольший индекс в массиве, равный количе-ство элементов минус 1. Если количество элементов массива равно 0, возвращается -1 (минус единица).
Вставить
Вставляет значение в массив по указанному индексу.
[ИТОГИ [<агрегатные функции>] ПО <Список полей> [,ОБЩИЕ]]
| В квадратных скобках приведены необязательные конструкции. Вертикальной чертой разделены конструкции, предполагающие выбор одного из нескольких элементов. Все конструкции языка запросов с примерами их использования приведены ниже.
| |
Автоупорядочивание /AUTOORDER
Ключевое слово АВТОУПОРЯДОЧИВАНИЕ позволяет включить режим автоматического формирования полей для упорядочивания результата запроса. Оно часто используется при построении отчетов.
Автоупорядочивание работает по следующим правилам:
| · | Если в запросе было указано предложение УПОРЯДОЧИТЬ ПО, то каждая ссылка на таблицу, находящаяся в этом предложении, будет заменена полями, по которым по умолчанию сортируется таблица (для справочников это код или наименование, для документов ? дата документа). Если поле для упорядочивания ссылается на иерархический справочник, то будет применена иерархическая сортировка по этому справочнику.
| |
| · | Если в запросе отсутствует предложение УПОРЯДОЧИТЬ ПО, но есть предложение ИТОГИ, тогда результат запроса будет упорядочен по полям, присутствующим в предложении ИТОГИ после ключевого слова ПО, в той же последовательности и в случае, если итоги рассчитывались по ссылочным полям, то по полям сортировки по умолчанию таблиц, на которые были ссылки.
| |
| · | Если в запросе отсутствуют предложения УПОРЯДОЧИТЬ ПО и ИТОГИ, но есть предложение СГРУППИРОВАТЬ ПО, тогда результат запроса будет упорядочен по полям, присутствующим в предложении, в той же последовательности и в случае если группировка велась по ссылочным полям, то по полям сортировки по умолчанию таблиц, на которые были ссылки.
| |
| · | И наконец, если в запросе отсутствуют предложения УПОРЯДОЧИТЬ ПО, ИТОГИ и СГРУППИРОВАТЬ ПО, результат будет упорядочен по полям сортировки по умолчанию для таблиц, из которых выбираются данные, в порядке их появления в запросе.
| |
ЧАС (<дата>)
| Выделяет часы из даты (от 0 до 23).
| |
ДеньГода (<дата>)
| Определяет номер дня в году по дате (от 1 до 366).
| |
ДеньНедели (<дата>)
| Определяет номер дня недели по дате (от 1 до 7).
| |
Диапазон
| Брюки детские
| | | | 100
| | | | 100 - 1000
| | | Рубашка «Ковбойка»
| | | | 1050
| | | | 1000 и выше
| | | Одежда
| | | |
| | | | Это группа
| | | Джинсы женские
| | | | 1100
| | | | 1000 и выше
| | | Свитер детский
| | | | 0
| | | | Не задана
| | | Сантехника
| |
| | | | Это группа
| | | Бытовая техника
| |
| | | | Это группа
| | | Раковина «Лилия»
| | | | 0
| | | | Не задана
| | | Мойдодыр «Аквариум»
| | | | 0
| | | | Не задана
| | | Смеситель «Ультра»
| | | | 750
| | | | 100 - 1000
|
ДЛЯ ИЗМЕНЕНИЯ
РегистрНакопления.УчетНоменклатуры.Остатки
| Необходимо понимать, что в транзакции любые данные защищены от изменения другими пользователями. Опция же ДЛЯ ИЗМЕНЕНИЯ нужна для блокировки от транзакционного чтения. Ее используют, чтобы как можно раньше сказать системе, что данная таблица должна быть заблокирована от чтения. При работе в клиент-серверном варианте блокировка накладывается только на записи, которые задействованы в запросе. Использование данного ключевого слова позволяет в момент обращения к запросу поставить одного из двух конкурирующих пользователей в состояние ожидания, пока другой проведет свой документ. Проще говоря, если не использовать данное ключевое слово, то два пользователя прочитают, что товар есть на складе, и как минимум один из них не сможет провести документ. А если применить ДЛЯ ИЗМЕНЕНИЯ, то в момент чтения данных (выполнения запроса) тот, кто позже начал, будет ждать, пока данные освободятся. Поэтому запрос с этим ключевым словом обычно ставят как можно раньше в процедуре проведения документа, чтобы уменьшить количество бесполезных действий.
| |
Дополнительно
На этой закладке устанавливаются дополнительные настройки запроса, например, исключение повторяющихся записей, а также блокировка данных для изменения.
Другие полезные методы
При работе с выборкой из результата запроса будут полезны следующие методы:
Единица измерения
| | Бумага
| | | | 130
| | | | Пачка
| | | Вилы
| | | | 1000
| | | | Шт
| | | Грабли
| | | | 1500
| | | | Шт
|
Ключевое слово КАК необязательно и может быть опущено, но для повышения наглядности его рекомендуется указывать, особенно на первых порах.
Ниже приведен пример того же запроса без ключевого слова КАК:
ВЫБРАТЬ Наименование Товар, Цена, ЕдИзм ЕдиницаИзмерения
ИЗ Справочник.Товары
УПОРЯДОЧИТЬ ПО Товар
Год
| | Иванов Иван Иванович
| | | | 25.12.2003
| | | | Ив
| | | | 25
| | | | 12
| | | | 2003
| | | Петров Петр Петрович
| | | | 05.07.2000
| | | | Пе
| | | | 5
| | | | 7
| | | | 2000
| | | Сидоров Иван Николаевич
| | | | 15.12.1995
| | | | Си
| | | | 15
| | | | 12
| | | | 1995
|
ГОД (<дата>)
| Выделяет год из даты. Возвращает число от 1 до 9999.
| |
Группа
| | 1С: Бухгалтерия 7.7
| | | | 35
| | | | Программы
| | | Клавиатура PS/2
| | | | 3
| | | | Клавиатуры
| | | Монитор 15" LG
| | | | 134,5
| | | | Мониторы
| | | Мышь 2-кноп PS/2
| | | | 1,2
| | | | Мыши
| | | Мышь М -S48
| | | | 0,8
| | | | Мыши
|
В данном примере того же эффекта можно добиться, если просто обращаться к имени поля через точку, что называется разыменованием ссылочных полей. При этом соединение таблиц производится неявно.
Следующий запрос эквивалентен предыдущему и использует разыменование полей:
ВЫБРАТЬ Номенклатура,
| Номенклатура.ЗакупочнаяЦена КАК Цена,
| |
| Номенклатура.Родитель КАК Группа
| | ИЗ Документ.РасходнаяНакладная.Состав
Возможность разыменования полей в 1С:Предприятии 8.0 допускает обращение к свойствам объектов через несколько точек, например, «Номенклатура.Поставщик.Страна». Это позволяет значительно упростить написание запросов.
Рассмотренное соединение относится к классу внутренних. В языке запросов системы 1С:Предприятие 8.0 существует возможность внешних соединений, которые могут быть левыми (LEFT OUTER), правыми (RIGHT OUTER) и полными (FULL OUTER).
Группировка
Если требуется сгруппировать результаты запроса, т.е. свернуть по группировочным полям, выберите поля, по которым будет выполнена группировка.
Возвращает в виде строки имя группировки текущей записи. Если группировки нет, возвращается пустая строка.
Иерархический обход
Рассмотрим другой способ обхода результата запроса ? иерархический. При данном варианте обходятся только записи, находящиеся на одном уровне. Для получения иерархической выборки из результата необходимо вызвать метод Выбрать объекта РезультатЗапроса с параметром ОбходРезультатаЗапроса.ПоГруппировкамСИерархией:
| СпособВыборки = ОбходРезультатаЗапроса.ПоГруппировкамСИерархией;
| |
| Выборка = РезультатЗапроса.Выбрать(СпособВыборки);
| |
| Выборка из результата запроса с иерархическим обходом в нашем примере обойдет только записи с номерами 1 и 11, так как только эти две записи находятся на самом верхнем уровне. Проиллюстрируем это, представив наш результат в виде дерева, где узлами будут итоговые записи, а листьями дерева будут детальные записи. Вот что у нас получится:
| |
Используется язык программирования:
Выборка= Справочники.Сотрудники.Выбрать();
Пока Выборка.Следующий() Цикл
| Если Выборка.Оклад > 10000 Тогда
| |
| Сообщить(Выборка.Наименование + " имеет оклад " + Выборка.Оклад);
| | КонецЦикла;
Используется механизм запросов:
Запрос = Новый Запрос("
| | ВЫБРАТЬ * ИЗ Справочник.Сотрудники
| | Выборка = Запрос.Выполнить().Выбрать();
Пока Выборка.Следующий() Цикл
| Сообщить(Выборка.Наименование + " имеет оклад " + Выборка.Оклад);
| | КонецЦикла;
| Обратите внимание на особенности второго варианта с использованием запроса:
| |
| · | внутри цикла не нужно фильтровать записи, поскольку запрос выполнил всю работу за нас;
| |
| · | вариант с запросом обычно выполняется быстрее, так как в клиент-серверном варианте работы запрос выполняется на сервере и не требуется передавать по сети весь справочник, который может быть очень большим.
| |
| В клиент-серверном варианте работы 1С: Предприятия 8.0 запросы будут транслироваться в SQL для выполнения в среде MS SQL Server. Сервер баз данных предпримет необходимые действия для оптимизации запроса.
| |
| Даже если вы работает в файловом варианте, то вариант с запросом обычно эффективнее обычного цикла для обработки больших справочников, списков документов и извлечения данных из регистров.
| |
| Но необходимо иметь в виду, что при использовании запроса, результат целиком помещается в память, тогда как выборка, сформированная средствами встроенного языка, загружает информацию порциями и позволяет перебрать большие списки объектов, не требуя значительного объема памяти.
| |
| Написание запроса требует не алгоритмического, а декларативного типа мышления, когда разработчик говорит не как сделать задачу, а что нужно получить в результате. При этом производится обработка не одной переменной или одной текущей строки, а всей таблицы или столбца. Разработчик должен мыслить множествам, чтобы решить поставленную задачу с помощью одного или нескольких запросов.
| |
| Заметим, что в приведенном выше примере мы рассмотрели самое простое применение механизма запросов. С помощью запросов можно не только отбирать нужные записи по любому условию, но также группировать, сортировать, подсчитывать итоги. И сейчас мы научимся все это делать!
| | <
table width="100%" cellpadding="0" cellspacing="0"> | | | <
table width="100%" cellpadding="0" cellspacing="0"> | |
| <
table width="100%" cellpadding="0" cellspacing="0"> | | |
На этой закладке определяется, по
На этой закладке определяется, по каким полям подсчитывать промежуточные итоговые данные, а также подсчитывать или нет общие итоги.
Итоги по группировкам
При расчете итогов по группировкам вычисляются значения агрегатных функций по выборкам с одинаковыми значениями полей, по которым производится группировка. Например, в следующей таблице значения группировок выделены жирным шрифтом:
Итоги по иерархии
Если группировочное поле является ссылкой на справочник, то для расчета итогов по группам справочника (или родительским элементам, если справочник состоит из одних элементов) необходимо указать ключевое слово ИЕРАРХИЯ. В этом случае в результат будут добавлены записи с итогами для уровней иерархии справочника.
Например, выберем записи справочника Номенклатура, рассчитаем объем продаж по каждой позиции и по группам справочника:
Клавиатуры
| | |
| | | Клавиатура LK-601 КВ-2000 PS/2
| | | | Расходная накладная 00032 от 25.07.2002 12:00:00
| | | Клавиатура LK-601 KB-2000 PS/2
| | | | Расходная накладная 00011 от 10.05.2002 12:00:00
| | | Клавиатура LK-601 KB-2000 PS/2
| | | | Расходная накладная 00020 от 02.08.2002 10:44:45
| | | |
Ключевое слово МЕЖДУ / BETWEEN
В языке запросов есть вспомогательное ключевое слово МЕЖДУ для задания интервалов. Например, если параметр МинЦена равен 1000, а МаксЦена ? 1500, тогда следующий запрос выберет товары с ценой из указанного интервала:
ВЫБРАТЬ Наименование,
ЗакупочнаяЦена КАК Цена
ИЗ Справочник.Номенклатура
ГДЕ ЗакупочнаяЦена МЕЖДУ &МинЦена И &МаксЦена
Ключевое слово ПЕРВЫЕ / ТОР
Данное ключевое слово позволяет ограничить выборку несколькими первыми записями. Часто это ключевое слово применяется в комбинации с сортировкой (см. предложение УПОРЯДОЧИТЬ ПО).
Допустим, требуется выбрать 3 самых дорогих товара. Это реализуется следующим запросом:
ВЫБРАТЬ ПЕРВЫЕ 3 Наименование, Цена
ИЗ Справочник.Номенклатура
УПОРЯДОЧИТЬ ПО Цена УБЫВ
Результат запроса будет такой:
Ключевое слово РАЗЛИЧНЫЕ/DISTINCT
Ключевое слово РАЗЛИЧНЫЕ позволяет оставить в результате запроса только отличающиеся строки. Например, если мы выбираем контрагентов из документа РасходнаяНакладная, то вполне вероятно, что один и тот же контрагент, может встретиться в нескольких накладных, поэтому без ключевого слова РАЗЛИЧНЫЕ он будет присутствовать в результате запроса несколько раз. Например, в результате приведенного ниже запроса несколько раз встречается контрагент ООО «Новый мир»:
ВЫБРАТЬ Контрагент ИЗ Документ.РасходнаяНакладная
Код:
//создание объекта Запрос
Запрос = Новый Запрос("
|ВЫБРАТЬ Код, Наименование
|ИЗ Справочник.Номенклатура");
//выполнение запроса и получение результата
РезультатЗапроса = Запрос .Выполнить();
//получение выборки из результата запроса
Выборка = РезультатЗапроса.Выбрать();
//обход записей в выборке
Пока Выборка.Следующий() Цикл
| Сообщить(Выборка.Наименование);
| | КонецЦикла;
| Два основных элемента механизма запросов ? это язык запросов и обход выборки из результата запроса. Именно в них заключена основная мощь механизма запросов, поэтому ниже они будут рассмотрены более подробно. Но прежде, чем мы перейдем к написанию запросов «с чистого листа», познакомимся с Конструктором запросов, который значительно упрощает освоение языка запросов.
| |
ВЫБРАТЬНаименование, ДатаПриема
| ПОДСТРОКА(Наименование,1,2) КАК Сокращение,
| |
| ДЕНЬ(ДатаПриема) КАК Число,
| |
| МЕСЯЦ(ДатаПриема) КАК Месяц,
| | ИЗ Справочник.Сотрудники
ВЫБРАТЬ
ВЫБОР
| Когда ЭтоГруппа = Истина Тогда "Это группа"
| |
| Когда ЗакупочнаяЦена >= 1000 Тогда "1000 и выше"
| |
| Когда ЗакупочнаяЦена >= 100 Тогда "100 - 1000"
| |
| Когда ЗакупочнаяЦена >= 10 Тогда "10 - 100"
| |
| Когда ЗакупочнаяЦена > 0 Тогда "0 - 10"
| | КОНЕЦ КАК Диапазон
ИЗ Справочник.Номенклатура
Запрос= Новый Запрос("ВЫБРАТЬ * ИЗ Документ.ПриходнаяНакладная
|ГДЕ Дата МЕЖДУ &НачДата и &КонДата");
Запрос.УстановитьПараметр("НачДата",ВыбНачалоПериода);
Запрос.УстановитьПараметр("КонДата",ВыбКонецПериода);
Результат = Запрос.Выполнить();
| В качестве параметра может быть передано любое значение, например, значение одного из примитивных типов (число, строка, дата, булево), ДокументСсылка, СправочникСсылка, список значений и т.д.
| |
| Группы справочника и список значений часто применяются с ключевым словом В. Если передается группа справочника (или родительский элемент для справочников из одних элементов), то можно применить конструкцию В ИЕРАРХИИ.
| |
| Например, покажем цены на товары из указанного списка:
| |
//1-й пример: отбор по списку товаров
Запрос = Новый Запрос("
|ВЫБРАТЬ * ИЗ Справочник.Номенклатура
|ГДЕ Ссылка В &СписокТоваров");
Запрос.УстановитьПараметр("СписокТоваров",СписокВыбранныхТоваров);
//2-й пример: отбор по группе товаров
Запрос = Новый Запрос("
| ВЫБРАТЬ * ИЗ Справочник.Номенклатура
| ГДЕ Ссылка В ИЕРАРХИИ &ГруппаТоваров");
Запрос.УстановитьПараметр("ГруппаТоваров",ВыбГруппа);
ВЫБРАТЬ
| Док.Номенклатура,Док.Номенклатура.Услуга КАК Услуга,
| |
| Док.Номенклатура.ЗакупочнаяЦена КАК ЗакупочнаяЦена,
| |
| Док.Количество, Док.Сумма,
| |
| ОстаткиСкл.КоличествоОстаток КАК КоличествоСкл,
| |
| Остатки.КоличествоОстаток, Остатки.СуммаОстаток
| | ИЗ
| Документ.РасходнаяНакладная.Состав КАК Док
| | ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
| РегистрНакопления.УчетНоменклатуры.Остатки(,
| |
| Номенклатура В (&ПарНоменклатура) И
| |
| Склад = &ПарСклад) КАК ОстаткиСкл
| | ПО
| Док.Номенклатура = ОстаткиСкл.Номенклатура
| |
| РегистрНакопления.СтоимостнойУчетНоменклатуры.Остатки(&Момент,
| |
| Номенклатура В (&ПарНоменклатура)) КАК Остатки
| |
| ПО Док.Номенклатура = Остатки.Номенклатура
| | ГДЕ Док.Ссылка = &Ссылка
Количество
| 00001
| | | | Мышь LOGITECH M-S48 PS/2
| | | | 10
| | | 00001
| | | | Мышь ОК-720 Mouse A4Tech PS/2
| | | | 2
| | | 00002
| | | | 1C: Аспект 7.7
| | | | 1
| | | 00003
| | | | Windows XP Home Edition
| | | | 1
| | | 00003
| | | | Доставка
| | | | 13
| | | 00003
| | | | Инсталляция ПО
| | | | 2
|
| | 1500000
| | | | 6000
| | | | 17000
| | | | 9000
| | | | 30
|
| Рассмотрим более подробно функцию КОЛИЧЕСТВО / COUNT. Эта функция подсчитывает количество значений параметра, попавших в выборку.
| |
| В отличие от других агрегатных функций она допускает три варианта использования:
| |
| · | Позволяет узнать количество строк в результате запроса. Для этого в качестве параметра функции надо указать звездочку («*»). Это наиболее часто встречающийся вариант использования функции КОЛИЧЕСТВО. Даже если в строке все поля содержат NULL, то такая строка тоже будет посчитана.
| |
| · | Позволяет подсчитать количество значений указанного поля, не являющихся NULL-значениями. В качестве параметра функции можно указывать ссылки на поля, содержащие значения любого типа, при этом NULL-значения игнорируются.
| |
| · | Позволяет узнать количество различных значений указанного поля. Для этого перед спецификацией поля надо указать ключевое слово РАЗЛИЧНЫЕ / DISTINCT, при этом NULL-значения игнорируются.
| |
| Например, с помощью функции КОЛИЧЕСТВО можно ответить на следующие вопросы:
| |
| · | Сколько сотрудников, у которых оклад больше заданной величины?
| |
| ВЫБРАТЬ КОЛИЧЕСТВО(*) КАК Количество
| |
| · | Сколько различных клиентов купили хоть что-нибудь за заданный период?
| |
| ВЫБРАТЬ КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Контрагент) КАК Количество
| |
| ИЗ Документ.РасходнаяНакладная
| |
| ГДЕ Дата МЕЖДУ &НачДата И &КонДата
| |
| | 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
|
| Организуем линейную выборку из результата запроса и обойдем ее при помощи метода СледующийПоЗначениюПоля:
| |
КОЛИЧЕСТВО (COUNT)
Подсчитывает количество значений, содержащихся в столбце. Если в качестве параметра данной функции передать звездочку («*»), то функция подсчитает количество строк в таблице результата запроса.
| Ниже приведен пример запроса с несколькими агрегатными функциями:
| |
КоличествоЧеловек
| | Бухгалтерия
| | | | 30000
| | | | 6000
| | | | 16000
| | | | 10000
| | | | 9
| | | Маркетинг
| | | | 40000
| | | | 6500
| | | | 15000
| | | | 11000
| | | | 7
| | | Снабжение
| | | | 30000
| | | | 7000
| | | | 12000
| | | | 9000
| | | | 8
| | | Руководство
| | | | 50000
| | | | 9000
| | | | 17000
| | | | 14000
| | | | 6
|
| В языке запросов можно группировать данные по нескольким полям, при этом будут подсчитаны агрегатные функции для каждой комбинации группировок:
| |
Консоль запросов
| Для системы 1С:Предприятие 8.0 была создана удобная обработка «Консоль запросов», которая поставляется на дисках информационнотехнологического сопровождения (ИТС). Эта обработка позволяет в режиме запуска «Предприятие» написать текст на языке запросов и тут же получить результат.
| |
| Все запросы хранятся в древовидном списке, который можно сохранить в файл и загрузить из файла. Результат запроса отображается в виде таблицы, дерева или выводится в табличный документ (отчет), который можно напечатать или скопировать в другую программу через буфер обмена. Кроме того, Консоль запросов позволяет получить результат запроса в виде сводной таблицы, для чего предназначена соответствующая закладка в нижней части формы.
| |
| Для написания текста запроса можно задействовать Конструктор запросов, описанный выше. Для этого достаточно щелкнуть правой кнопкой на текстовом поле, в которое вводится запрос, и выбрать пункт «Конструктор запросов».
| |
Конструкция СОЕДИНЕНИЕ...ПО/JOIN...ON
Важной возможностью языка запросов системы 1С:Предприятие 8.0 является обращение сразу к нескольким таблицам. При этом их можно соединять определенным образом. Например, необходимо выбрать все проданные товары и вывести их в отчет с указанием группы, к которой они относятся. Это делает представленный ниже запрос:
ВЫБРАТЬДок.Номенклатура,
| Спр.ЗакупочнаяЦена КАК Цена,
| | ИЗ Документ.РасходнаяНакладная.Состав КАК Док
| СОЕДИНЕНИЕ Справочник. Номенклатура КАК Спр
| |
| ПО Док.Номенклатура = Спр.Ссылка
| | Результат этого запроса показан ниже:
Контрагент
| | ООО Новый мир
| | | ЗАО Стройметмаш
| | | ООО Новый мир
| | | ООО Механика
| |
Если же указать ключевое слово РАЗЛИЧНЫЕ, то повторяющиеся записи из результата запроса будут удалены:
ВЫБРАТЬ РАЗЛИЧНЫЕ Контрагент ИЗ Документ. РасходнаяНакладная
| ООО Новый мир
| | | ЗАО Стройметмаш
| | | ООО Механика
| |
Куплено
| Автохозяйство №34
| | | | 10 698,6
| | | Алекс-2002
| | | | 76 519,2
| | | Завод РТИ
| | | | 15 007,9
| | | Магазин на ул. Алексеева
| | | | 63 525,1
| | | Эльбрус
| | | | 31 084,7
|
| Обратите внимание, что ключевое слово ГДЕ применяется здесь только для отбора записей за нужный период. Затем данные группируются по контрагенту с подсчетом суммы проданных товаров, и к получившимся строкам применяется условие ИМЕЮЩИЕ.
| |
Курс
| | EUR
| | | | 30,8717
| | | GBR
| | | |
| | | USD
| | | | 31,4568
| | | Рубль
| | | | 1
|
КВАРТАЛ (<дата>)
| Определяет номер квартала по дате (от 1 до 4).
| |
ЛЕВОЕ [ВНЕШНЕЕ] СОЕДИНЕНИЕ
означает, что в результат запроса надо включить комбинации записей из обеих исходных таблиц, которые соответствуют указанному условию. Но, в отличие от внутреннего соединения, в результат запроса надо включить еще и записи из первого источника (указанного слева от слова СОЕДИНЕНИЕ), для которых не найдено соответствующих условию записей из второго источника.
Таким образом, в результат запроса будут включены все записи из первого источника; они будут соединены с записями из второго источника при выполнении указанного условия. Строки результата запроса, для которых не найдено соответствующих условию записей из второго источника, будут содержать значение NULL в полях, формируемых на основании записей из этого источника.
Обратите внимание, что NULL-значения не являются нулем или пустой строкой. Это специальные маркеры, обозначающие неуказанные (отсутствующие) значения или значения, не имеющие смысла.
Например, нужно показать курсы всех валют, которые хранятся в регистре сведений КурсыВалют. Возможно, что для некоторой валюты не будет найдено соответствующей записи в регистре сведений, но она также должна попасть в отчет (запросы к регистрам сведений и таблица СрезПоследних описаны в главе Регистры сведений ):
ВЫБРАТЬСпр.Наименование, Peг.Курс
ИЗ Справочник.Валюты КАК Спр
ЛЕВОЕ ВНЕШНЕЕ СОЕДИНЕНИЕ
| РегистрСведений.КурсыВалют.СрезПоследних КАК Peг
| | ПО Спр.Ссылка = Peг.Валюта
Результат запроса показан в следующей таблице:
Линейный обход
Первый и самый простой способ обхода ? линейный. При линейном обходе выборка будет выдавать записи в той последовательности, в которой они располагаются в результате запроса. В нашем примере это будут записи с номерами 1, 2, 3, 4, 5 и так далее до записи с номером 20.
Для получения линейной выборки необходимо вызвать метод Выбрать объекта РезультатЗапроса без параметров, либо с параметром ОбходРезультатаЗапроса. Прямой.
Логические операторы И, ИЛИ, НЕ
В условиях можно использовать логические операторы И, ИЛИ, НЕ, с помощью которых можно строить достаточно сложные логические выражения.
Например, выберем товары, произведенные в России по цене, меньшей определенного значения:
ВЫБРАТЬ Наименование,
ЗакупочнаяЦена КАК Цена,
СтранаПроисхождения КАК Страна
ИЗ Справочник.Номенклатура
ГДЕ СтранаПроисхождения = "Россия" И ЗакупочнаяЦена < 1000
Лопата
| | Лопата
| |
Простой запрос с итогами по группировкам выглядит следующим образом:
МЕСЯЦ (<дата>)
| Выделяет месяц из даты (от 1 до 12).
| |
Мониторы
| |
| | | Монитор 15" LG Studioworks 575N
| | | | Расходная накладная 00019 от 06.06.2002 12:00:00
| | | Монитор 15" LG Studioworks 575N
| | | | Расходная накладная 00006 от 15.02.2002 12:00:00
| | | Монитор 15" LG Studioworks 575N
| | | | Расходная накладная 00018 от 15.06.2002 12:00:00
|
НачалоПериода ( <дата>, <ТипПериода> )
| Возвращает начало периода по заданной дате. В качестве параметра ТипПериода передается Год, Месяц, Неделя, День, Час и т.д.
| |
Наименование
| | Магазин на ул. Алексеева
| | | Максимус
| |
В выражении шаблона был использован служебный символ «%», обозначающий любую последовательность символов. Кроме этого, есть и другие служебные символы для задания выражения шаблона.
Следующие символы в строке шаблона являются служебными и имеют особый смысл:
| 00014
| | | | 1С:Бухгалтерия ПРОФ версия 7.7
| | | 00016
| | | | 1С:Торговля и Склад 7.7 Проф
| | | 00009
| | | | Windows XP Home Edition Russian CD
| | | 00010
| | | | Windows XP Home Edition Russian UPG CD
| | | 00011
| | | | Windows XP Professional Russian CD
| | | 00041
| | | | Доставка
| | | 00042
| | | | Инсталляция ПО
| | | 00018
| | | | Клавиатура Apple Pro Keyboards
|
| Сортировка часто применяется с ключевым словом ПЕРВЫЕ. Например, следующий запрос сортирует товары по убыванию цены и показывает 5 самых дорогих товаров:
| |
| ВЫБРАТЬ ПЕРВЫЕ 5 Код, Наименование, ЗакупочнаяЦена КАК Цена
| |
| ИЗ Справочник.Номенклатура
| |
| Результат запроса показан в таблице:
| |
НайтиСледующий
| Позволяет найти запись с заданными значениями некоторых полей.
| |
| Ниже приведен простейший пример обхода выборки с помощью метода Следующий:
| |
НайтиСледующий
(СтруктураПоиска)Цикл
| Сообщить("Сотрудник" + Выборка.Наименование);
| | КонецЦикла;
//2-й вариант: поиск значения по заданной колонке
//выберем всех сотрудников, принятых в 2003 году
Пока Выборка.
(2003, "Год") Цикл
| Сообщить("Сотрудник" + Выборка.Наименование);
| | КонецЦикла;
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|