Для формирования и выполнения запросов к таблицам базы данных в платформе 1С используется специальный объект языка программирования Запрос. Создается этот объект вызовом конструкции Новый Запрос. Запрос удобно использовать, когда требуется получить сложную выборку данных, сгруппированную и отсортированную необходимым образом. Классический пример применения запроса - получение сводки по состоянию регистра накопления на определенный момент времени. Так же, механизм запросов позволяет легко получать информацию в различных временных разрезах.
Текст запроса – это инструкция, в соответствии с которой должен быть выполнен запрос. В тексте запроса описывается:
таблицы информационной базы, используемые в качестве источников данных запроса;
поля таблиц, которые требуется обрабатывать в запросе;
правила группировки;
сортировки результатов;
и т. д.
Инструкция составляется на специальном языке – языке запросов и состоит из отдельных частей – секций, предложений, ключевых слов, функций, арифметических и логических операторов, комментариев, констант и параметров.
Язык запросов платформы 1С очень похож на синтаксис других SQL-языков, но имеются отличия. Основными преимуществами встроенного языка запросов являются: разыменование полей, наличие виртуальных таблиц, удобная работа с итогами, нетипизированные поля в запросах.
Рекомендации по написанию запросов к базе данных на языке запросов платформы 1С:
1) Текст запроса может содержать предопределенные данные конфигурации, такие как:
значения перечислений;
предопределенные данные:
справочников;
планов видов характеристик;
планов счетов;
планов видов расчетов;
пустые ссылки;
значения точек маршрута бизнес-процессов.
Также текст запроса может содержать значения системных перечислений, которые могут быть присвоены полям в таблицах базы данных: ВидДвиженияНакопления, ВидСчета и ВидДвиженияБухгалтерии. Обращение в запросах к предопределенным данным конфигурации и значениям системных перечислений осуществляется с помощью литерала функционального типа ЗНАЧЕНИЕ. Данный литерал позволяет повысить удобочитаемость запроса и уменьшить количество параметров запроса.
Пример использования литерала ЗНАЧЕНИЕ:
ГДЕ Город = ЗНАЧЕНИЕ(Справочник.Города.Москва)
ГДЕ Город = ЗНАЧЕНИЕ(Справочник.Города.ПустаяСсылка)
ГДЕ ТипТовара = ЗНАЧЕНИЕ(Перечисление.ВидыТоваров.Услуга)
ГДЕ ВидДвижения = ЗНАЧЕНИЕ(ВидДвиженияНакопления.Приход)
ГДЕ ТочкаМаршрута = ЗНАЧЕНИЕ(БизнесПроцесс.БизнесПроцесс1.ТочкаМаршрута.Действие1
2) Использование инструкции АВТОУПОРЯДОЧИВАНИЕ в запросе может сильно время выполнения запроса, поэтому, если сортировка не требуется, то лучше вообще ее не использовать. Во большинстве случаях лучше всего применять сортировку с помощью инструкции УПОРЯДОЧИТЬ ПО.
Автоупорядочивание работает по следующим принципам:
Если в запросе было указано предложение УПОРЯДОЧИТЬ ПО, то каждая ссылка на таблицу, находящаяся в этом предложении, будет заменена полями, по которым по умолчанию сортируется таблица (для справочников это код или наименование, для документов – дата документа). Если поле для упорядочивания ссылается на иерархический справочник, то будет применена иерархическая сортировка по этому справочнику.
Если в запросе отсутствует предложение УПОРЯДОЧИТЬ ПО, но есть предложение ИТОГИ, тогда результат запроса будет упорядочен по полям, присутствующим в предложении ИТОГИ после ключевого слова ПО, в той же последовательности и, в случае если итоги рассчитывались по полям – ссылкам, то по полям сортировки по умолчанию таблиц, на которые были ссылки.
Если в запросе отсутствуют предложения УПОРЯДОЧИТЬ ПО и ИТОГИ, но есть предложение СГРУППИРОВАТЬ ПО, тогда результат запроса будет упорядочен по полям, присутствующим в предложении, в той же последовательности и, в случае если группировка велась по полям – ссылкам, то по полям сортировки по умолчанию таблиц, на которые были ссылки.
В случае же, если в запросе отсутствуют предложения и УПОРЯДОЧИТЬ ПО, ИТОГИ и СГРУППИРОВАТЬ ПО, результат будет упорядочен по полям сортировки по умолчанию для таблиц, из которых выбираются данные, в порядке их появления в запросе.
В случае, если запрос содержит предложение ИТОГИ, каждый уровень итогов упорядочивается отдельно.
3) Что бы избежать повторного запроса к базе данных при выводе результата запроса пользователю (например, построение запроса или отображение результата запроса с помощью табличного документа) полезно использовать инструкцию ПРЕДСТАВЛЕНИЕССЫЛКИ, которая позволяет получать представление ссылочного значения. Пример:
Так же возможно использование инструкции ПРЕДСТАВЛЕНИЕ - предназначена для получения строкового представления значения произвольного типа. Отличие этих инструкций в том, что в первом случае, если инструкции передать ссылку, результатом будет строка, В остальных случаях результатом будет значение переданного параметра. Во втором случае, результатом инструкции всегда будет строка!
4) Если в запросе имеется поле с составным типом, то для таких полей возникает необходимость привести значения поля к какому-либо определенному типу с помощью инструкции ВЫРАЗИТЬ, что позволит убрать лишние таблицы из левого соединения с полем составного типа данных и ускорить выполнение запроса. Пример:
Имеется регистра накопления ОстаткиТоваров, у которого поле Регистратор имеет составной тип. В запросе выбираются Дата и Номер документов ПоступлениеТоваров, при этом при обращении к реквизитам документа через поле Регистратор не происходит множество левых соединений таблицы регистра накопления с таблицами документов-регистраторов.
Если приведение типа считается не осуществимым, то результатом приведения типа будет значение NULL.
5) Не стоит забывать про инструкцию РАЗРЕШЕННЫЕ, которая означает, что запрос выберет только те записи, на которые у текущего пользователя есть права. Если данное слово не указать, то в случае, когда запрос выберет записи, на которые у пользователя нет прав, запрос отработает с ошибкой.
6) В случае, если в запросе используется объединение, и в некоторых частях объединения присутствуют вложенные таблицы (документ с табличной частью), а в некоторых нет, возникает необходимость дополнения списка выборки полями – пустыми вложенными таблицами. Делается это при помощи ключевого слова ПУСТАЯТАБЛИЦА, после которого в скобках указываются псевдонимы полей, из которых будет состоять вложенная таблица. Пример:
7) Что бы в результат запроса не попали повторяющиеся строки, следует использовать инструкцию РАЗЛИЧНЫЕ, потому что так нагляднее и понятнее, а инструкция СГРУППИРОВАТЬ ПО применяется для группировки с помощью агрегатных функций. Ксати, при использовании агрегатных функций предложение СГРУППИРОВАТЬ ПО может быть и не указано совсем, при этом все результаты запроса будут сгруппированы в одну единственную строку. Пример:
8) Инструкция СГРУППИРОВАТЬ ПО позволяет обращаться к полям верхнего уровня, без группировки результатов по этим полям, если агрегатные функции применены к полям вложенной таблицы. Хотя в справке 1С написано, при группировке результатов запроса в списке полей выборки обязательно должны быть указаны агрегатные функции, а помимо агрегатных функций в списке полей выборки допускается указывать только поля, по которым осуществляется группировка. Пример:
9) Инструкция ЕСТЬNULL предназначена для замены значения NULL на другое значение, но не забываем, что второй параметр будет преобразован к типу первого в случае, если тип первого параметра является строкой или числом.
10) При обращении к главной таблице можно в условии обратиться к данным подчиненной таблицы. Такая возможность называется разыменование полей подчиненной таблицы.
Пример (поиск документов, содержащих в табличной части определенный товар):
Преимущество этого запроса перед запросом к подчиненной таблице Приходная.Товары в том, что если есть дубли в документах, результат запроса вернет только уникальные документы без использования ключевого слова РАЗЛИЧНЫЕ.
11) Интересный вариант оператора В - это проверка вхождения упорядоченного набора в множество таких наборов (Поле1, Поле2, ... , ПолеN) В (Поле1, Поле2, ... , ПолеN).
Пример:
12) При любой возможности используйте виртуальные таблицы запросов. При создании запроса система предоставляет в качестве источников данных некоторое количество виртуальных таблиц - это таблицы, которые так же являются результатом запроса, который система формирует в момент выполнения соответствующего участка кода.
Разработчик может самостоятельно получить те же самые данные, которые система предоставляет ему в качестве виртуальных таблиц, однако алгоритм получения этих данных не будет оптимизирован, так как:
Все виртуальные таблицы параметризованы, т. е. разработчику предоставляется возможность задать некоторые параметры, которые система будет использовать при формировании запроса создания виртуальной таблицы. В зависимости от того, какие параметры виртуальной таблицы указаны разработчиком, система может формировать РАЗЛИЧНЫЕ запросы для получения одной и той же виртуальной таблицы, причем они будут оптимизированы с точки зрения переданных параметров.
Не всегда разработчик имеет возможность получить доступ к тем данным, к которым имеет доступ система.
13) В клиент-серверном варианте работы функция ПОДСТРОКА() реализуется при помощи функции SUBSTRING() соответствующего оператора SQL, передаваемого серверу баз данных SQL Server, который вычисляет тип результата функции SUBSTRING() по сложным правилам в зависимости от типа и значений ее параметров, а так же в зависимости от контекста, в котором она используется. В большинстве случаев эти правила не оказывают влияния на выполнение запроса, но бывают случаи, когда для выполнения запроса существенна максимальная длина строки результата, вычисленная SQL Server. Важно иметь в виду, что в некоторых контекстах использования функции ПОДСТРОКА() максимальная длина ее результата может оказаться равной максимальной длине строки ограниченной длины, которая в SQL Server равна 4000 символам. Это может привести к неожиданному аварийному завершению выполнения запроса:
Microsoft OLE DB Provider for SQL Server: Warning: The query processor could not produce a query plan from the optimizer because the total length of all the columns in the GROUP BY or ORDER BY clause exceeds 8000 bytes.
HRESULT=80040E14, SQLSTATE=42000, native=8618
Чтобы избежать такой ошибки, не рекомендуют использовать функцию ПОДСТРОКА() с целью приведения строк неограниченной длины к строкам ограниченной длины. Вместо нее лучше использовать операцию приведения типа ВЫРАЗИТЬ().
14) С осторожностью используйте ИЛИ в конструкции ГДЕ, так как использование условия с ИЛИ может значительно "утяжелить" запрос. Решить проблему можно конструкцией ОБЪЕДИНИТЬ ВСЕ. Пример:
15) Условие НЕ В в конструкции ГДЕ увеличивает время исполнения запроса, так как это своего рода НЕ (ИЛИ1 ИЛИ2 ... ИЛИn), поэтому для больших таблиц старайтесь использовать ЛЕВОЕ СОЕДИНЕНИЕ с условием ЕСТЬ NULL. Пример:
16) При использовании Временных таблиц нужно индексировать поля условий и соединений в этих таблицах, НО, при использовании индексов запрос может выполняться еще медленнее. Поэтому необходимо анализировать каждый запрос с применением индекса и без, замерять скорость выполнения запроса и принимать окончательное решение.
Если вы помещаете во временную таблицу данные, которые изначально индексированы по некоторым полям, то во временной таблице индекса по этим полям уже не будет.
17) Если вы не используете Менеджер временных таблиц, то явно удалять временную таблицу не требуется, она будет удалена после завершения выполнения пакетного запроса, иначе следует удалить временную таблицу одним из способов: командой УНИЧТОЖИТЬ в запросе, вызвать метод МенеджерВременныхТаблиц.Закрыть().
Для пользователя:
Последовательность документов есть в УПП, УТ (8), ТиС, ПУБ (7). Операции – Проведение документов, на закладке «Восстановление последовательностей» приведены все имеющиеся в программе последовательности и указана дата актуальности каждой из них. То есть если в июне 2010 года мы видим такое:
то это плохо. Партионный учет давно неактуален, значит – все значения себестоимости, которые появляются в отчетах, врут. (Учет кадров и налоговый учет УСН в данной базе не ведется).
Что значит последовательность? Строго говоря, одним из правил учета является его оперативность, т.е. отражение хозяйственных операций по мере их возникновения. 1 июня на склад поступило 10 штук товара А, потом 10 июня продано 8 штук. Если проводить эти документы (Поступление товаров и услуг, Реализация товаров и услуг) строго в хронологическом порядке, то последовательность установится сначала на 1 июня, потом на 10 июня. Т.е. ее граница будет сдвигаться вперед каждым документом, и итоги (количество, сумма, себестоимость) будут актуальными на каждый момент времени. Если же потом, задним числом, провести еще один документ (Реализация товаров и услуг) от 8 июня, которым будет оформлена реализация 7 штук товара А, программа дает это сделать беспрепятственно. Граница последовательности при этом установится на 8 июня, на этот документ. То есть информация ДО ввода этого документа верна, а ПОСЛЕ – уже нет. При восстановлении последовательности (перепроведении документов, входящих в последовательность), документ от 10 июня проведен не будет, потому что нет необходимого количества товара А. Далее пользователь должен искать причину этой ошибки, устранять и восстанавливать последовательность заново.
Как часто восстанавливать последовательность? Как минимум – перед выполнением регламентных операций, формированием значимых отчетов и т.п. Поскольку любое перепроведение документа (относящегося к последовательности) сдвигает ее границу, имеет смысл закрывать для редактирования прошлые периоды (Сервис – Установка даты запрета изменения данных).
В Бухгалтерии последовательности нет (за исключением кадровых приказов – в 8.1), но есть возможность автоматического перепроведения документов за период. Перед закрытием месяца это делать необходимо (Операции – Проведение документов). Для программиста: Последовательность – объект метаданных 1С – предназначена для упорядоченного хранения множества документов согласно дате и времени.
Граница последовательности (ГП) – позиция, последнего введённого документа в последовательность. Если после ГП есть другие документы в последовательности, то последовательность считается нарушенной и её необходимо восстановить.
Логически - последовательность можно условно представить как «Общий» журнал документов входящих в эту последовательность. Условно, потому, что на последовательностях строится логика учета.
У некоторых последовательностей, для дополнительного контроля автоматически при движении регистров, отслеживается связь: регистр – последовательность. Если изменился регистр, должна измениться и последовательность.
Физически – последовательность состоит из двух таблиц:
1. Таблица регистрации;
2. Таблица границ.
Таблица регистрации (ТР) – коллекция зарегистрированных в последовательности документов в разрезе измерений. В случае повторной записи документа сначала удаляется старая запись, затем записывается новая.
Таблица границ (ТГ) – хранит границу последовательности в разрезе измерений, одно измерение – одна запись если измерений нет, то у ТГ одна запись. Запись ТГ показывает, какой документ в ТР является последним правильно проведённым, т.е. не нарушившим правильное ведение учёта.
Обе таблицы идентичны по составу колонок: «Период», «Регистратор», «Измерение».
Восстановить последовательность возможно путём простого программного переноса ГП (если вы уверены, что итоги не нарушены) на последний документ в последовательности или повторным, последовательным проведением всех документов от ГП до последнего по времени документа в последовательности. Для исправления последовательности существует штатная обработка «Проведение документов».
Механизм «последовательность» имеет подчинённые объекты, свойство – измерения.
Измерения – это разрезы последовательности. Измерения, условно разбивают последовательность на несколько логически целых частей.
Измерение позволяет, в случае необходимости, перепроводить не все документы, входящие в последовательность, а только те которые содержат данное измерение, что ускоряет скорость работы при восстановлении последовательности.
Измерения повышают производительность системы в целом, так как при записи и проведении захватывается не вся таблица целиком, а только те её строки, которые соответствуют данному измерению.
Регистрация документа в последовательности, т.е. в ТР, производится в момент его записи.
Регистрация документа в последовательности может осуществляться автоматически, под руководством системы, если свойство «Заполнение последовательностей» документа будет установлено в «Заполнять автоматически» если иначе, то сам разработчик описывает правила регистрации.
Запись в ТГ происходит при проведении документа.
При проведении документа, его движения учитываются в:
· «Оперативном учёте» - записывает движения документа в регистрах;
· «Бухгалтерском учёте» - запись проводок.
ПоследовательностьМенеджер.< ИмяПоследовательности > - Данный менеджер предназначен для управления последовательностью:
Последовательность.«ИмяПоследовательности».Восстановить
Последовательность.«ИмяПоследовательности».ПолучитьГраницу
Последовательность.«ИмяПоследовательности».ПолучитьГраницы
Последовательность.«ИмяПоследовательности».Принадлежит
Последовательность.«ИмяПоследовательности».Проверить
Последовательность.«ИмяПоследовательности».СоздатьНаборЗаписей
Последовательность.«ИмяПоследовательности».УстановитьГраницу
Вся работа «ПоследовательностьМенеджер» складывается из анализа и работы с ТР и ТГ. Например, метод «Проверить» - если документ в ТГ, есть последний в ТР, значит, последовательность не нарушена и наоборот и т.д. Что такое Последовательности Документов
В процедуру ПриОткрытии или в конец модуля добавить:
Где НомерСоглашения - Колонка в списке регистра сведений по которой нужно сортировать!
Далее щелкнув правой клавишей мыши на списке и зайдя в пункт Сортировка - увидим что стала доступна возможность сортировки по НомерСоглашения.
Как отсортировать список документов по признаку ПРОВЕДЕН?
Сортировка динамических списков (ЖурналДокументовСписок)
Добавлять элементы настройки порядка в динамические списки нельзя.
Если индексирование для графы установлено, то соответсвующий элемент настройки порядка уже есть, надо его просто включить:
Для вывода иерархического справочника в отчет с сохранением иерархии необходимо пользоваться запросом аналогичным следующему:
Данный запрос выбирает все записи из справочника и производит упорядочивание по иерархии. Результат будет упорядочен по наименованию, с учетом иерархии.
Для того чтобы группы справочника размещались выше элементов необходимо в данном запросе заменить предложение УПОРЯДОЧИТЬ ПО на следующее:
Результат по-прежнему будет упорядочен по иерархии, однако группы будут располагаться выше элементов.
Возможна также замена предложения УПОРЯДОЧИТЬ ПО на предложение АВТОУПОРЯДОЧИВАНИЕ. В этом случае результат будет упорядочен в соответствии с настройками справочника, т.е. если в справочнике указано, что группы должны располагаться выше элементов, то они будут расположены выше.
Получить иерархическую структуру справочника также возможно и при помощи итогов.
Функция Представление()
Функция представление предназначена для получения текстового представления любого значения, которое может быть получено при помощи языка запросов. Функция Представление() работает как для ссылочных, так и для примитивных типов. Для ссылочных типов результат функции полностью аналогичен получению поля "Представление" от ссылки, переданной в качестве параметра функции. Для примитивных типов, результатом работы функции является строка, в которую было преобразовано значение, переданное в качестве параметра. Особенностью данной функции является то, что ее результат не может быть использован в выражении. Такая особенность связана с тем фактом, что преобразование значений в строку осуществляется уже при получении данных из результата запроса, т.к. преобразование произвольного значения в строку при исполнении запроса на сервере, не осуществляется, в силу того, что при преобразовании значений в строку необходимо учитывать локальные настройки.
Использование функции Представление() имеет ряд преимуществ по сравнению с использованием поля "Представление". Например, в случае если поле, от которого получается представление, может содержать как ссылочные, так и примитивные типы, получение поля "Представление" через точку от такого поля приведет к тому, что представления для значений примитивного типа не будут получены. Если же, для такого поля применить функцию Представление(), то строковое представление будет получено вне зависимости от типа значения, содержащегося в поле. Кроме того, в случае если функция Представление() применяется к полю, которое является ссылкой более чем на три таблицы, язык запросов получает из базы данных только ссылочные значения, а значения представлений получает одним или несколькими дополнительными запросами. Такое поведение позволяет более эффективно получать представления для полей, которые ссылаются на большое количество таблиц (например, на любой справочник), за счет того, что в исполняемый запрос не будет помещаться большое количество соединений, которые необходимы для получения полей из которых состоит представление.
Применение функции Представление() также может быть полезным при получении представления поля - перечисления, в случае исполнения запроса через COM-соединение
Поле Представление
Каждая объектная таблица в информационной базе имеет виртуальное поле - "Представление". Это поле содержит текстовое представление объекта. В запросе возможно получать данное поле точно также как и другие поля таблиц, однако никакие операции с данным полем выполнять нельзя. Данная особенность связана с тем, что это поле является виртуальным, и, на самом деле, при получении данного поля из базы данных, запрос получает несколько полей, а при получении значения поля из результата запроса преобразовывает полученные значения в строку. Таким образом, единственное, что можно сделать с полем "Представление", это получить его в результат запроса.
Как следствие, результат запроса не рекомендуется упорядочивать по полю "Представление", т.к. это не приведет к желаемому результату - результат запроса будет упорядочен в порядке возрастания ссылок объектов. Подробнее об этом можно прочитать в разделе "Особенности упорядочивания по ссылочным полям".
При работе с запросами нередко возникает ситуация, когда результат запроса необходимо упорядочить по представлению некоторого ссылочного поля. Например, необходимо упорядочить список номенклатуры по представлению. Заметим, что упорядочивание непосредственно по полю Представление приведет к не вполне ожидаемому результату - результат будет упорядочен в порядке возрастания ссылок объектов. Данный эффект проявляется из-за того, что поле Представление является виртуальным и на уровне базы данных состоит из нескольких полей, из которых уже в момент получения значения поля получается строка - представление. При упорядочивании же по этому полю произойдет последовательное упорядочивание по реальным полям, из которого оно состоит, в результате чего упорядочивание произойдет не по строковому представлению, а по внутренней ссылке поля.
Пример неправильного упорядочивания:
На самом деле, упорядочивание по представлению является довольно сомнительной операцией с точки зрения полезности результата. Для примера достаточно посмотреть на представления документов - эти строки содержат в себе даты, а упорядочивание дат как строк не даст осмысленного результата. Для того чтобы обеспечить упорядочивание, которое будет отвечать ожиданиям пользователей, следует использовать упорядочивание непосредственно по ссылочному полю и дополнительно указать в запросе ключевое слово АВТОУПОРЯДОЧИВАНИЕ. В таком случае запрос получит для каждого ссылочного поля реальные поля, по которым его необходимо упорядочить (для документа это будет дата и номер, для справочника - основное представление) и произведет упорядочивание по ним.