При работе с прямыми запросами к базе данных 1С 7.7 (в частности, при использовании ВК 1SQLite или прямых SQL-запросов к MS SQL Server) разработчики часто сталкиваются с необходимостью получить сумму документа-основания. В отличие от стандартного языка запросов платформы 1С 8.x, архитектура реляционных таблиц 1С 7.7 имеет специфические особенности, которые вызывают затруднения при попытке объединить данные нескольких видов документов.
Рассмотри подробно, как устроено хранение данных в 1С 7.7, почему нельзя обойтись простым соединением журнала с одной таблицей и какие способы оптимизации запросов существуют.
Чтобы понять, почему возникает сложность при запросе сумм документов-оснований, разберем структуру хранения данных платформы 1С 7.7:
_1SJOURN) содержит только общие системные реквизиты: дату, номер, идентификатор документа IDDOC, код вида документа IDDOCDEF, а также флаги проведения и удаления. Суммы документов в общей таблице журнала не хранятся.DH<ID>) содержат реквизиты шапки конкретного вида документа (включая итоговые суммы). Для каждого вида документа создается отдельная физическая таблица.DT<ID>) хранят строки табличных частей документов каждого вида.IDDOC документа-основания в SQL, приходится использовать функции работы со строками, такие как SUBSTR.Таким образом, если документ-основание может относиться к нескольким различным видам (например, ПоступлениеТМЦ, ВозвратОтПокупателя, ПоступлениеПрочее), реквизит суммы каждого из этих документов физически находится в разных SQL-таблицах шапок (DH...).
Сформулируем классический подход к получению суммы документа-основания через прямой запрос. Для извлечения сумм нам потребуется последовательно соединить основные таблицы шапок предполагаемых видов документов через LEFT JOIN и применить функцию COALESCE для выбора первого непустого значения.
Разберем пример построения такого запроса на языке SQL (1SQLite / T-SQL):
SELECT
Жур.IdDoc as [Докум $Документ.СчетФактураПолученный],
COALESCE(DH_Пост.SP123, DH_Возвр.SP456, DH_Проч.SP789, 0) AS СуммаОснования
FROM
[Журнал] AS Жур
INNER JOIN
[Документ.СчетФактураПолученный] AS СФ ON СФ.IdDoc = Жур.IdDoc
LEFT JOIN
[Документ.ПоступлениеТМЦ] AS DH_Пост ON DH_Пост.IdDoc = SUBSTR(СФ.ДокументОснование, 10, 9)
LEFT JOIN
[Документ.ВозвратОтПокупателя] AS DH_Возвр ON DH_Возвр.IdDoc = SUBSTR(СФ.ДокументОснование, 10, 9)
LEFT JOIN
[Документ.ПоступлениеПрочее] AS DH_Проч ON DH_Проч.IdDoc = SUBSTR(СФ.ДокументОснование, 10, 9)
WHERE
Жур.date BETWEEN :ДатаС AND :ДатаПо
AND (Жур.Closed & 1 = 1)
В приведенном примере мы задействуем LEFT JOIN для каждого возможного вида документа-основания, после чего с помощью COALESCE получаем правильную сумму. Однако при большом количестве видов документов такое количество соединений может снизить скорость выполнения запроса.
Проанализируем практические способы ускорения выборки данных в 1С 7.7 при использовании библиотеки 1SQLite и прямых запросов.
Для ускорения чтения журнала документов важно обращаться непосредственно к таблице журнала по индексированным полям (виду документа и дате), избегая лишних соединений в секции FROM.
SELECT
Жур.IdDoc as [Докум $Документ.СчетФактураПолученный]
FROM
[Журнал] as Жур
WHERE
(Жур.IdDocDef = :ВидДокумента.СчетФактураПолученный)
and (Жур.date between :ДатаС and :ДатаПо)
and (Жур.Closed & 1 = 1)
В коде 1С с помощью метаданных можно перед выполнением запроса проанализировать, какие именно виды документов могут являться основаниями в заданном периоде. Это позволяет подставлять в LEFT JOIN только 2–3 реально используемые таблицы вместо десятков возможных.
Вместо множественных LEFT JOIN к каждой таблице шапки можно собрать временную таблицу с суммами всех нужных документов через UNION ALL, а затем выполнить один единый JOIN с получившейся выборкой.
Если конфигурация подлежит доработке, реквизит суммы можно сделать Общим реквизитом со свойством «Переносить в журнал». В этом случае платформа создаст соответствующее поле непосредственно в таблице _1SJOURN, что позволит получать сумму любого документа напрямую из журнала без соединения с таблицами DH....
Таким образом, архитектура 1С 7.7 требует применения внешних соединений (LEFT JOIN) со всеми возможными таблицами шапок документов-оснований, либо оптимизации выборки с помощью временных таблиц и динамического формирования SQL-кода.