Запросы в 1С 7.7

Запросы 1С 7.7

БыстрыеИтоги.zip

Список рассматриваемых тем

Общие сведения.

Ограничения текущей версии.

Краткие запросы.

Сложные запросы.

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

Пример запроса по характеристикам субконто.

Пример произвольного отбора таблицы итогов средствами SQL-сервера.

Пример периодического запроса.

Работа с произвольной базой данных.

Обновление одной версии класса на другую.

 

Общие сведения: читать всем

Работа класса тестировалась с релизами 1С:Предприятия 7.70.18, 7.70.21 и 7.70.25 под управлением ОС Windows XP с версиями компоненты 1cpp.dll – от 1.8.1.4 и выше; версиями MS SQL Server – MS SQL 2000 (без сервис-паков) и MS SQL 2000 sp3a.

Данный текст предполагает, что вы досконально знаете достоинства и недостатки стандартных бухгалтерских запросов 1С:Предприятия, и что вы по крайней мере в общих чертах знакомы с методикой оптимального программирования для 1С:Предприятия SQL-версии. Также, данный текст не является заменителем синтаксис-помощника и не содержит полных сведений о каждой функции или процедуре класса. В тексте на различных примерах показывается, в каких случаях какие методы класса помогут достичь наилучших результатов с точки зрения скорости выполнения запросов и трудозатрат программиста.

Класс изначально не предназначен для тупой имитации методов объекта «БухгалтерскиеИтоги» (далее по тексту – «БИ»). Несмотря на то, что большинство стандартных методов объекта «БИ» или уже реализовано (с набором параметров, наиболее часто используемых при построении запросов), или планируется реализовать в следующих версиях класса, функционал класса не исчерпывается такой имитацией. Напротив, при построении и анализе запросов рекомендуется отойти от стандартных методов и пользоваться методами класса, отсутствующими в типовом объекте «БИ» – в особенности методами групповой обработки данных. Именно за счет групповой обработки данных на сервере и будет достигаться основной выигрыш в производительности.

В отличие от методов групповой обработки, перекладывающих основную работу на SQL-сервер, методы перебора выборок сымитированы на языке 1С‑Предприятия и работают на локальной рабочей станции, поэтому такие переборы (ВыбратьСубконто()/ПолучитьСубконто() и пр.) практически всегда работают медленнее методов типового объекта «БИ». Для больших запросов (от 500-1000 строк в таблице запроса) проигрыш в скорости можно значительно снизить, проиндексировав таблицу выборок (см. метод СоздатьИндекс()); но в любом случае, настоятельно рекомендуется как можно меньше использовать методы простого перебора итогов – иначе класс просто не оправдает своего названия.

 

Ограничения 

  • Временно отсутствует поддержка запросов по корсчетам и корсубконто;
  • Временно отсутствует позиционирование итогов на счета-группы (метод ПолучитьСчет() всегда позиционируется на счете-элементе);
  • Отсутствует поддержка запросов по произвольному (нефиксированному) набору видов субконто – иными словами, нельзя вызвать метод ИспользоватьСубконто(), не указав вид субконто;
  • Поддерживаются только разделители учета типа «Справочник»;
  • При построении выборок к результатам запроса, детализированного по периодам, выборка по периодам должна быть последней (самой глубокой) выборкой – т.е. в теле цикла ПолучитьПериод() нельзя строить никакие другие выборки к данному запросу.

Нюансы, которые выглядят как ограничения, но на самом деле не являются ограничениями:

  • При получении результатов запроса в таблицу значений не выполняется проверка на активно-пассивность текущих счетов – сальдо всегда интерпретируется как дебетовое;
  • В запросах, детализированных по периодам, суммы начального и конечного сальдо периодов зависят от контекста выборки. При получении результатов такого запроса в таблицу значений суммы начального и конечного сальдо периодов не заполняются автоматически и должны быть рассчитаны программно в соответствии с требуемым контекстом (нужным набором группировок). Суммы начального и конечного сальдо остальных группировок в таблице такого запроса определяются как итог по соответствующим колонкам по всем строкам, соответствующим требуемому набору группировок.

 

Виды запросов 1С 7.7

Класс поддерживает два вида запросов: т.н. «краткие» запросы (аналог методов получения остатков и оборотов по счетам) и «полные», или сложные запросы (аналог режима запросов).

 

Краткие запросы 1С 7.7

Краткие запросы не могут получать итоги по группам субконто, списку значений со значениями субконто, группам или списку валют, списку счетов, группе или списку разделителей учета. При выполнении краткого запроса к не-текущей ИБ не проверяется флаг «только обороты» для используемых субконто.

Собственно запрос посылается на сервер одним из методов СНД(), СНК(), ДО(), КО(), СКД(), СКК() с указанием счета запроса или его кода, типа необходимого результата («С», «В» или «К»), валюты (если тип результата – «В») и необходимых субконто. Перед вызовом этих методов должен быть установлен период запроса (например, методом ПериодМ()).

Пример использования:

В результате в переменную ДО будет записана сумма дебетового оборота по разделителю учета Фирма, счету 62.1 и первому субконто Контрагент за месяц, соответствующий дате ДатаМесяца.

Краткие запросы кэшируют обороты и остатки по переданным значениям отбора (разделитель учета, счет, валюта и субконто). Таким образом, для получения кредитовых оборотов за тот же период и по тем же фирме и контрагенту достаточно будет написать:

или просто:

Если вместо этого записать полную формулу расчета кредитового оборота,

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

В отличие от методов расчета остатков и оборотов объекта «БИ», при построении кратких запросов методы класса могут оперировать не только с периодами, кратными календарным месяцам. Доступны следующие методы описания периодов:

Список доступных методов класса:

 

Сложные запросы 1С 7.7

Запрос данного типа предполагает обращение к накопленным бухгалтерским итогам со сложным набором параметров. При построении запросов данного типа возможен отбор и/или разворот по группам или спискам субконто, группам или спискам произвольного числа характеристик субконто, группам или спискам счетов, группам или спискам разделителей учета, группам или спискам валют.

Результаты запросов данного типа могут быть сохранены во временную таблицу на сервере для последующей обработки процедурами класса (методами индексации, группового чтения данных и/или построения выборок) или не сохраняться на сервере и возвращаться пользователю в сыром виде (см. метод ПолучитьТаблицуИтогов()). Данные методы обращения к результатам являются взаимоисключающими.

Методы построения и перебора выборок могут работать в двух режимах: режиме неиндексированного и индексированного запроса. При неиндексированном запросе (данный режим устанавливается по умолчанию при вызове метода ВыполнитьЗапрос()) текущий контекст выборки считывается во внутренний кэш; все последующие обращения к результатам запроса в этом контексте (построение вложенных выборок и отбор итогов) обрабатываются локально (без обращений на сервер) методами класса, написанными на языке 1С-Предприятия .

В режиме индексированного запроса каждая выборка строится отдельным запросом к индексированной временной таблице на сервере. Для включения режима индексации следует явно указать порядок анализа выборки при вызове метода СоздатьИндекс() (метод должен быть вызван сразу после процедуры ВыполнитьЗапрос()). Допускается неоднократный вызов данного метода к результатам одного и того же запроса, – в ряде случаев это позволяет объединить несколько запросов в один.

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

 

Рассмотрим пример такого запроса.

Данный запрос использует два индекса для получения двух разных выборок в таблицы значений. Первая таблица заполняется с учетом отбора по второму субконто; вторая – с учетом отбора по счету.  В данном случае отбор выполняется средствами SQL-сервера.

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

При написании запросов рекомендуется всегда избегать обхода всего запроса целиком методами типа ПолучитьСубконто() или ПолучитьСчет(). Намного быстрее будет работать перебор таблицы значений с итогами запроса, отобранными по интересующим вас параметрам (см. текущий пример). Единственным исключением из этого правила является анализ начальных или конечных сальдо группировок по периодам; в таких случаях методы групповой обработки не выигрывают в производительности из-за необходимости дополнительных расчетов на каждое значение периода (см. примечание выше).

 

В следующем примере подробнее остановимся на характеристиках субконто 1С 7.7

При инициализации запроса описывается, что данные должны дополнительно группироваться по полям «Код» и «Группа» справочника основных средств, причем в запросе такие поля будут доступны через идентификаторы «ИнвНомер» и «ГруппаОС» соответственно. После выполнения запроса его результат индексируется в интересующем нас направлении (сначала обрабатывается группировка «ГруппаОС», и только потом группировка по первому субконто).

В качестве характеристики субконто может быть использован любой реквизит справочника, любой реквизит шапки документа или общий реквизит документа, а также реквизит ТЧ документа, по которому установлен флаг «Суммирование итогов по колонке». Исключение составляют реквизиты-строки неограниченной длины и периодические реквизиты справочников. Заполнение таблицы итогов значениями соответствующих реквизитов, сортировка и отбор по таким значениям выполняется средствами SQL-сервера.

 

Приведем пример произвольного отбора таблицы итогов в 1С 7.7 средствами SQL-сервера.

Метод ВыполнитьИнструкцию() может быть выполнен как в контексте текущей выборки, так и вне его. Если метод выполняется с учетом контекста, в текст запроса перед условием пользователя (сразу после ключевого слова where) вставляется условие, гарантирующее отбор в соответствии с текущим контекстом. В примере выше итоговый текст запроса будет выглядеть так:

Если в запросе отсутствует ключевое слово where, условие будет добавлено с учетом возможного присутствия ключевых слов group by и order by. Ситуация с неоднократным вхождением слова where и указанных ключевых слов не обрабатывается; при ошибках, связанных с неоднократным вхождением этих ключевых слов следует отключить флаг построения запроса в контексте и написать необходимые условия отбора самостоятельно.

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

 

Четвертый пример – пример периодического запроса в 1С 7.7

Класс допускает использование вложенных периодических выборок ВыбратьДокументы()/ВыбратьПроводки() в контексте запроса, детализированного по проводкам. Метод  ПолучитьДокумент() позиционируется на очередном документе в таблице запроса; при этом обращение к результатам запроса вернет сумму остатков или оборотов по документу в целом (в соответствии с контекстом выборки). Соответственно, во вложенную выборку проводок попадают только проводки текущего документа. Вне выборки по документам метод ВыбратьПроводки() сформирует выборку проводок без отбора по значению документа.

Учтите, что методы построения выборок ВыбратьДокументы(), ВыбратьПроводки() и ВыбратьПериоды() следует использовать ТОЛЬКО с парными им методами обращения к выборкам ПолучитьДокумент(), ПолучитьПроводку() и ПолучитьПериод() соответственно. Нельзя объявить выборку методом ВыбратьДокументы() и получать ее результаты методом ПолучитьПериод().

Список доступных методов класса:

 

 Работа с произвольной базой данных 1С 7.7

При создании объекта класса происходит настройка SQL-соединения на текущую базу данных. При необходимости параметры соединения можно изменить методом УстПараметрыПодключения(RecordSet, ИД_РУ). В первом параметре передается объект класса ODBCRecordSet или его производное, подключенный к необходимой БД; во втором параметре задается внутренний идентификатор разделителя учета подключаемой БД (в том виде, в каком он описан в таблице проводок). В случае, если подключаемая БД не использует разделитель учета, второй параметр можно опустить.

Вызов метода УстПараметрыПодключения() трактуется как отключение от текущей базы данных и подсоединение к новой БД. Повторная ре-инициализация объекта класса с восстановлением параметров предыдущего соединения не предусмотрена.

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

 

Вызов данного метода после смены подключения ОБЯЗАТЕЛЕН!

Пример:

ИспользоватьРазделительУчета(Значение, ТипФильтра, ИмяТаблицы):

Значение: (не обязателен) значение, по которому производится фильтрация результатов запроса – внутренний идентификатор (Строка(9)) элемента справочника или список значений с такими идентификаторами;

ТипФильтра: (не обязателен) тип фильтра (1 – разворот, 2 – отбор, 3 – нет фильтра), по умолчанию 1;

ИмяТаблицы: имя SQL-таблицы, соответствующей справочнику разделителей учета.

ИспользоватьСубконто(ВидСубконто, Значение, ТипФильтра, ТипСубконто, ИмяТаблицы):

ВидСубконто: числовой номер субконто, соответствующий номеру субконто в счете запроса;

Значение: (не обязателен) значение, по которому производится фильтрация результатов запроса – внутренний идентификатор (Строка(9)) субконто или список значений с такими идентификаторами;

ТипФильтра: (не обязателен) тип фильтра (1 – разворот, 2 – отбор, 3 – нет фильтра), по умолчанию 1;

ТипСубконто: тип используемого субконто (строка вида «Справочник.Контрагенты», «Дата» и пр.). Обращение к данному субконто при формировании выборки может быть выполнено как по числовому идентификатору выборки, так и по типу субконто (ВыбратьСубконто(1) или ВыбратьСубконто(«Справочник.Контрагенты»));

ИмяТаблицы: (для субконто типа «Документ» или «Справочник») имя SQL-таблицы, соответствующей шапке данного вида документа или данному виду справочника.

Еще раз: при подключении к произвольной БД внутренние группировки запроса не сопоставляются элементам базы данных и возвращаются в виде идентификаторов объектов (строковый тип). Строковое представление некоторых видов группировок может быть получено альтернативными методами. Например, строковое представление субконто типа «Справочник» может быть получено методом ПредставлениеСубконто() при условии, что до выполнения запроса была создана характеристика данного вида субконто по наименованию или коду.

Пример без комментариев:

 

Обновление одной версии класса на другую в 1С 7.7

В режиме запроса класс использует собственную хранимую процедуру SQL_AccntQuery. Если при создании объекта класса на сервере уже существует процедура с таким именем, в целях минимизации временных затрат ее перезапись НЕ ВЫПОЛНЯЕТСЯ. При обновлении одной версии класса на другую программист должен самостоятельно позаботиться об обновлении хранимой процедуры – программно (методом ПерезаписатьПроцедуруЗапроса()) или вручную (удалив с сервера старую версию процедуры)

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