При работе с высоконагруженными базами на платформе 1С 7.7 стандартных средств получения итогов по регистрам часто становится недостаточно. В таких случаях разработчики прибегают к использованию прямых запросов к SQL-серверу (обычно через внешнюю компоненту 1С++). Одной из наиболее частых задач является получение оборотов регистра в разрезе документов. Однако при использовании виртуальных таблиц новички часто сталкиваются с ошибками именования столбцов или непониманием структуры данных. Рассмотрим подробно, как правильно извлекать информацию о документах-регистраторах.
Часто при переходе от запросов к физическим таблицам (например, RAxxxx) к виртуальным таблицам (например, $РегистрОбороты) возникает ошибка "Недопустимое имя столбца IDdocDef". Разберем причину этой ситуации.
В физических таблицах движений 1С 7.7 действительно существует поле IDDocDef, которое хранит числовой идентификатор вида документа. Однако виртуальные таблицы 1С++ являются абстракцией (подзапросом), которая переопределяет имена полей для удобства разработчика и унификации кода. Внутри виртуальной таблицы $РегистрОбороты поле, отвечающее за вид документа, называется ВидДокумента. Проанализируем пример исправленного кода:
SELECT
RIGHT(Рег.ПозицияДокумента, 9) [Док $Документ],
Рег.ВидДокумента AS Док_вид,
Рег.ОстатокТовараПриход as ОстатокТовара,
Рег.ПродСтоимостьПриход as ПродСтоимость
FROM
$РегистрОбороты.ПартииТоваров(:ДатаНач,
:ДатаКон,
Документ,
,
Контрагент = :ВыбКонтрагент AND Статус = :ВыбСтатус,
,
(ОстатокТовара, ПродСтоимость)) as Рег
Как мы видим, замена IDdocDef на ВидДокумента полностью решает проблему доступа к идентификатору метаданных документа в контексте виртуальной таблицы.
Для идентификации конкретного экземпляра документа в 1С 7.7 используется понятие позиции документа. В прямых запросах это поле имеет тип char(23) и содержит в себе три важные составляющие, склеенные в одну строку:
YYYYMMDD.HHMMSS.IDDoc).Чтобы получить ссылку на документ, которую 1С++ сможет типизировать (превратить в объект), мы используем конструкцию RIGHT(Рег.ПозицияДокумента, 9) и типизацию через квадратные скобки [Док $Документ]. Если нам нужно получить дату документа прямо из позиции, мы можем применить функцию LEFT(Рег.ПозицияДокумента, 8).
Для эффективной работы крайне важно понимать, как устроена структура параметров макроса $РегистрОбороты. Рассмотрим их по порядку, чтобы выяснить, как управлять детализацией данных:
Документ. Также возможны варианты: Период, День, Неделя, Месяц и т.д.Товар, Склад), SQL-сервер сгруппирует данные только по ним, что значительно ускорит выполнение запроса на больших объемах данных.В зависимости от типа регистра (регистр остатков или регистр оборотов), к именам ресурсов в виртуальной таблице добавляются суффиксы. Рассмотрим, как это работает:
Для регистров остатков (как в примере ПартииТоваров) доступны три варианта:
ИмяРесурсаПриход — сумма всех положительных движений.ИмяРесурсаРасход — сумма всех отрицательных движений.ИмяРесурсаОборот — результирующая разница (Приход - Расход).Для регистров оборотов доступен только один вариант:
ИмяРесурсаОборот — сумма всех движений за указанный период.Важный нюанс: Если в параметре "Периодичность" указано значение Документ, то виртуальная таблица автоматически включает в результат поля ПозицияДокумента и ВидДокумента. При этом происходит автоматическая группировка данных в пределах одного документа по всем измерениям, входящим в расчет.
Выясним причину, по которой иногда требуется дополнительная группировка в самом SQL-запросе. По умолчанию виртуальная таблица "схлопывает" записи. Однако, если вы выбираете дополнительные поля, не входящие в стандартный набор виртуальной таблицы, вам придется использовать стандартную SQL-группировку GROUP BY.
Посмотрим на пример, когда мы хотим получить итоги по документам, но с фильтрацией по измерениям через 5-й параметр:
SELECT
Рег.ВидДокумента [ВидДок],
RIGHT(Рег.ПозицияДокумента, 9) [Док $Документ],
Рег.Товар [Товар $Справочник.Номенклатура],
SUM(Рег.КоличествоОборот) as Количество
FROM
$РегистрОбороты.ОстаткиТоваров(:НачДата, :КонДата, Документ, , , (Товар), (Количество)) as Рег
GROUP BY
Рег.ВидДокумента,
Рег.ПозицияДокумента,
Рег.Товар
В данном примере мы явно указываем измерение Товар в 5-м параметре. Это заставляет виртуальную таблицу выполнять расчет только по этому измерению, игнорируя остальные (например, Склад или Проект), что существенно экономит ресурсы сервера.
Подведем итог: использование ВидДокумента вместо IDdocDef, правильное извлечение IDDoc из ПозицияДокумента и грамотное использование списка измерений в параметрах виртуальной таблицы позволяют создавать быстрые и надежные отчеты на платформе 1С 7.7, работающие напрямую с базой данных SQL.