Регистры бухгалтерии. Еще одна таблица оборотов ДТ / КТ

22.08.20

Разработка - Механизмы типовых конфигураций

Виртуальная таблица оборотов ДТ / КТ регистра бухгалтерии. Особенности и применение.

Введение

В предыдущей статье "Регистры бухгалтерии. Виртуальная таблица оборотов" мы рассмотрели работу таблицы оборотов регистра бухгалтерии, коснулись некоторых особенностей ее работы как в части формируемых SQL-запросов платформы, так и в части работы с параметрами этой таблицы. Сегодня мы снова вернемся к оборотам, но в этот раз это будет виртуальная таблица "Обороты Дт/Кт".

Все данные для публикации получены с помощью инструментов:

Эта таблица используется реже, чем обычная таблица оборотов и далее мы выясним почему. Но некоторые отчеты в типовых конфигурациях ее все же используют:

  • Анализ состояния налогового учета по налогу на прибыль
  • Анализ состояния налогового учета по УСН
  • Валовая прибыль
  • Регистры БУ субъектов малого предпринимательства
  • И некоторые другие.

Давайте рассмотрим, что эта таблица позволяет сделать и чем она отличается от обычных оборотов. А позже "копнем" как она работает на уровне базы данных.

Первый взгляд

Начнем со сравнения таблиц "Обороты" и "ОборотыДтКт". Если смотреть на доступные поля и параметры, то можно выделить следующие различия:

  • В таблице "Обороты" доступны поля оборотов по ДТ и КТ для балансовых ресурсов. Для типового регистра это ресурс "Сумма". Если в таблице оборотов доступны как общая сумма оборотов, так и по ДТ и КТ, то для таблицы "ОборотыДтКт" доступен только общее поле "СуммаОборот".
  • Для небалансовых ресурсов отличие заключается в том, что в таблице "Обороты" для них кроме оборотов по ДТ и КТ присутствует общий оборот. В таблице "ОборотДтКт" общего оборота нет.

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

В таблице "Обороты" параметры виртуальных таблиц делятся не на "Дт / Кт", а на основной счет + его аналитика и корреспондентский счет + его корр. аналитика. Смысл практически тот же самый, но за большим исключением: если в таблице "ОборотыДтКт" отборы устанавливаются именно по счету ДТ и/или по счету КТ, то в обычной таблице оборотов отбор устанавливается без явного указания стороны проводки.

Проще показать на примере. Допустим, у нас есть вот такой запрос.

ВЫБРАТЬ
	ХозрасчетныйОборотыДтКт.СчетДт КАК СчетДт,
	ХозрасчетныйОборотыДтКт.КоличествоОборотДт КАК КоличествоОборотДт,
	ХозрасчетныйОборотыДтКт.СчетКт КАК СчетКт,
	ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК КоличествоОборотКт,
	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот
ИЗ
	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалоПериода, &КонецПериода, , СчетДт = &Счет, , , , ) КАК ХозрасчетныйОборотыДтКт

Сделав отбор, например, по счету 10.11.1 за 2019 год мы получили такой результат:

СчетДт КоличествоОборотДт СчетКт КоличествоОборотКт СуммаОборот
10.11.1 1 000 10.10 1 000 1 000 000

То есть количественный оборот как по ДТ, так и по КТ равен 1000. Оборот по сумме равен 1000000. Далее сделаем примерно такой же запрос, но к таблице "Обороты" с теми же значениями отборов:

ВЫБРАТЬ
	ХозрасчетныйОбороты.Счет КАК Счет,
	ХозрасчетныйОбороты.СуммаОборотДт КАК СуммаОборотДт,
	ХозрасчетныйОбороты.КоличествоОборотДт КАК КоличествоОборотДт,
	ХозрасчетныйОбороты.КорСчет КАК КорСчет,
	ХозрасчетныйОбороты.СуммаОборотКт КАК СуммаОборотКт,
	ХозрасчетныйОбороты.КоличествоОборотКт КАК КоличествоОборотКт,
	ХозрасчетныйОбороты.СуммаОборот КАК СуммаОборот,
	ХозрасчетныйОбороты.КоличествоОборот КАК КоличествоОборот
ИЗ
	РегистрБухгалтерии.Хозрасчетный.Обороты(&НачалоПериода, &КонецПериода, , Счет = &Счет, , , , ) КАК ХозрасчетныйОбороты

Вот такой результат мы получили:

Счет СуммаОборотДт КоличествоОборотДт КорСчет СуммаОборотКт КоличествоОборотКт СуммаОборот КоличествоОборот
10.11.1 1 000 000 1000 10.10 200 000 50 800 000 9950
10.11.1     20.01 10 000 2000 -10 000 -2000
10.11.1     26 4 000 25 -4 000 -25
10.11.1     44.01 20 000 50 -20 000 -50

Мы получили обороты с другими корреспондирующими счетами (44.01, 26, 20.01), но сейчас они нас не интересуют. Просто знаем, что таблица "Обороты" позволила их получить. А вот таблица "ОборотыДтКт" их не показала. Почему? Да потому что в проводках эти счета находятся на стороне ДТ, а мы явно указали отбор по ДТ и они в этот отбор не входят. Таблица же оборотов не учитывает явную сторону проводки, а лишь собирает данные по указанному счету как с дебетовой стороны, так и с кредитовой и группирует показатели в общий результат.

Посмотрите на все сделанные корреспонденции счетов за тот же период с участием счета 10.11.1. На стороне дебета он есть только для проводки "ДТ 10.11.1 - КТ 10.10". Именно поэтому только обороты по этой корреспонденции счетов попали в результат, когда отбор по ДТ = "10.11.1" для таблицы "ОборотыДтКт".

  СчетДт   СчетКт
44.01 10.11.1
26 10.11.1
10.11.1 10.10
10.10 10.11.1
20.01 10.11.1

Это важное отличие таблицы "ОборотыДтКт" от обычной таблицы оборотов: мы можем явно указать сторону счета (или другой произвольной аналитики) в проводке для фильтра и оперировать результатами запроса к этой виртуальной таблице точно зная где образовался нужный показатель - по дебету или кредиту.

Если же мы сделаем в обычной таблице оборотов отбор по счету "10.10" (с которым корреспондировал 10.11.1) и оставим результат только для корреспонденции этих двух счетов, то увидим следующее:

Счет СуммаОборотДт КоличествоОборотДт КорСчет СуммаОборотКт КоличествоОборотКт СуммаОборот КоличествоОборот
10.10 200 000 50 10.11.1 1 000 000 1000 -800 000 -950

То есть, таблица "Обороты" получила данные оборотов по счету "10.10" с корреспондирующим счетом "10.11.1" не смотря на то, что мы указали его в отборе по измерению "Счет" (а не корр. счет) этой виртуальной таблицы. Подробнее о принципе работы виртуальной таблицы "Обороты" Вы можете прочитать в прошлой публикации "Регистры бухгалтерии. Виртуальная таблица оборотов".

Таким образом, для получения оборотов по счету самым эффективным способом является использование виртуальной таблицы "Обороты" без получения данных по кор. счету (об этом мы говорили в предыдущей статье). Если получать корр. аналитику через эту таблицу, то не будут использоваться итоги и запрос может быть тяжелее, чем ожидается. Без корр. аналитики платформа 1С попытается максимально использовать данные таблиц итогов.

Таблица же "ОборотыДтКт" подходит для более специфичных задач, когда необходимо получать обороты с конкретными фильтрами по счету, аналитике или ресурсам с указанием явной стороны проводки - ДТ или КТ. Таблица является самой тяжелой среди всех виртуальных таблиц регистра бухгалтерии, т.к. она никогда не использует рассчитанные итоги, но об этом мы еще поговорим далее. Поэтому если есть возможность использовать обычную таблицу оборотов - делайте именно так. Если нет, то с осторожностью и рациональным подходом, используйте таблицу оборотов ДТ / КТ.

Есть, конечно, еще виртуальные таблицы "Остатки" и "ОстаткиИОбороты", но о них речь пойдет в будущих публикациях. Сейчас лишь отмечу, что в некоторых случаях можно использовать и эти таблицы вместо оборотов по ДТ / КТ, но этот случай выходит за рамки публикации.

Спускаемся глубже

Настало время рассмотреть какие запросы формирует платформа 1С при работе с виртуальной таблицей оборотов ДТ / КТ.

Простой запрос

Начнем с простого примера - получим обороты для счетов со стороны дебета по сумме и количеству. Чисто для эксперимента не будем указывать никаких параметров виртуальной таблицы или других условий.

ВЫБРАТЬ
	ХозрасчетныйОборотыДтКт.СчетДт КАК СчетДт,
	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот,
	ХозрасчетныйОборотыДтКт.КоличествоОборотДт КАК КоличествоОборотДт
ИЗ
	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(, , , , , , , ) КАК ХозрасчетныйОборотыДтКт

Один небольшой запрос на языке запросов 1С, но большой SQL-запрос на стороне базы данных (на самом деле еще не очень большой).

SELECT
    T1.AccountDtRRef, -- СчетДт
    T1.Fld790Turnover_, -- СуммаОборотДт
    T1.Fld792TurnoverDt_ -- КоличествоОборотДт
FROM (
    SELECT
        T2._AccountDtRRef AS AccountDtRRef, -- СчетДт
        CAST(SUM(T2._Fld790) AS NUMERIC(21, 2)) AS Fld790Turnover_, -- Сумма
        CAST(SUM(T2._Fld792Dt) AS NUMERIC(21, 3)) AS Fld792TurnoverDt_ -- КоличествоДт
    FROM dbo._AccRg786 T2 -- РегистрБухгалтерии.Хозрасчетный.Основная
    WHERE ((T2._Fld774 = @P1)) -- Разделитель данных
        AND (T2._Active) = 0x01 -- Активность
    GROUP BY T2._AccountDtRRef -- Счет
    -- Хотя бы один из ресурсов должен быть НЕ равен 0
    HAVING (CAST(SUM(T2._Fld790) AS NUMERIC(21, 2))) <> 0.0 
        OR (CAST(SUM(T2._Fld792Dt) AS NUMERIC(21, 3))) <> 0.0
    ) T1

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

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

Добавим немного параметров

Совсем немного изменим запрос, добавив отбор по периоду, счету ДТ и виду субконто. Для порядка еще и по организации сделаем отбор.

ВЫБРАТЬ
	ХозрасчетныйОборотыДтКт.СчетДт КАК СчетДт,
	ХозрасчетныйОборотыДтКт.СубконтоДт1 КАК СубконтоДт1,
	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот,
	ХозрасчетныйОборотыДтКт.КоличествоОборотДт КАК КоличествоОборотДт
ИЗ
	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалоПериода, &КонецПериода, , СчетДт = &СчетДт, &ВидСубконто, , , Организация = &Организация) КАК ХозрасчетныйОборотыДтКт

И снова один маленький запрос на языке запросов 1С, и уже несколько SQL-запросов на стороне базы данных.

 
 Запрос на получение информации о счете в параметре виртуальной таблицы
 
 Большой запрос на получение данных из регистра

Первым запросом платформа 1С получает настройки счета, который мы установили в отборах. Если бы мы также установили отбор по кредиту, то был бы сделан еще один запрос для этого счета.

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

Все это дополняется условиями на основную таблицу по счету ДТ, организации и также периоду. Ну и конечно же присутствуют отборы по разделителям данных, куда уж без них :)

На финальном этапе результат группируется по измерениям регистра и субконто, а после отсекаются записи без заполненной аналитики по ресурсам.

Получим все

Рассмотрим кратко еще один пример. Тот же самый запрос, но уже добавлены условия по стороне кредита: счет КТ, вид субконто:

ВЫБРАТЬ
	ХозрасчетныйОборотыДтКт.СчетДт КАК СчетДт,
	ХозрасчетныйОборотыДтКт.СубконтоДт1 КАК СубконтоДт1,
	ХозрасчетныйОборотыДтКт.КоличествоОборотДт КАК КоличествоОборотДт,
	ХозрасчетныйОборотыДтКт.СчетКт КАК СчетКт,
	ХозрасчетныйОборотыДтКт.СубконтоКт1 КАК СубконтоКт1,
	ХозрасчетныйОборотыДтКт.КоличествоОборотКт КАК КоличествоОборотКт,
	ХозрасчетныйОборотыДтКт.СуммаОборот КАК СуммаОборот
ИЗ
	РегистрБухгалтерии.Хозрасчетный.ОборотыДтКт(&НачалоПериода, &КонецПериода, , СчетДт = &СчетДт, &ВидСубконтоДт, СчетКт = &СчетКт, &ВидСубконтоКт, Организация = &Организация) КАК ХозрасчетныйОборотыДтКт

Как уже упоминалось ранее, в этом случае платформа сгенерирует два запроса для получения информации по счетам: один для ДТ, другой для КТ.

 
 Получение информации по счетам

Когда настройки счетов получены начинается самое интересное - длинный запрос получения данных.

 
 Еще один длинный запрос

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

Немного о производительности

Ранее уже упоминалось, что таблица оборотов по ДТ / КТ является одной из самых тяжелых среди всех виртуальных таблиц регистра бухгалтерии. Основная причина - то что эта таблица не использует итоги и всегда получает данные из основных таблиц регистра (основной таблицы и значений субконто).

Это достаточно тяжелая операция, если в базе миллионы проводок, а фильтры, накладываемые через параметры виртуальных таблиц, дают достаточно низкую селективность, что приводит к операциям сканирования. В большинстве случаев подобные запросы выполняются СУБД в следующей последовательности (пример сделан для последнего запроса):

1. Сначала отбираются записи из основной таблицы регистра с учетом отборов по счету ДТ и счету КТ, т.к. платформа 1С создает штатные индексы для таких отборов.

 
 Используемые штатные индексы

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

 
 План запроса для получения данных из основной таблицы регистра

Сначала выполняется получение записей с отбором по счету ДТ (индекс _AccRg786_3) и счету КТ (индекс _AccRg786_4) отдельными операциями. Результаты объединяются через вложенные циклы. Далее результат фильтруется по периоду (индекс _AccRg786_1).

Но и это еще не все. После выполняется получение данных в таблице значений субконто.

 
 План запроса получения данных значений субконто

 
 Используемые штатные индексы

Так как таблица значений субконто соединяется дважды, то СУБД дважды выполняет операцию получения записей. Что логично :) Используется для этого индекс по периоду, который позволяет максимально эффективно присоединить к основной таблице записи по периоду, регистратору, виду субконто и виду корреспонденции. Эффективность этой части запроса будет зависеть от того на сколько эффективно отработало получение данных из основной таблицы до этого. Если отбор по основной таблице вернул большой объем данных, то высока вероятность, что СУБД проигнорирует индексы и ей будет проще получить значения субконто простым сканированием таблиц.

Создать же эффективную выборку данных из основной таблицы очень проблематично, разве что указав короткий период в отборе или добавив отбор по регистратору. В остальных случаях отбор скорее всего будет неселективным и сканирования таблицы будет трудно избежать.

Конечно, план запроса не всегда будет таким и все зависит от объема данных, состояния индексов и статистик и, разумеется, СУБД. Но смысл, думаю, должен быть понятен.

Идем дальше

Регистр бухгалтерии - не простой как в реализации, так и в использовании. Не зря в типовых конфигурациях развивается идея делать отложенное проведение по нему, чтобы не увеличивать нагрузку при оперативной работе. Но выхода нет. Какие задачи - такой и регистр!

Платформа 1С - это место компромиссов и регистр бухгалтерии - один из них.

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

Все данные для публикации получены с помощью инструментов:

Всем хорошего дня!

Другие ссылки

Авторские разработки

 
 Другие разработки (8 штук, бесплатные и за $m)

регистр бухгалтерии внутреннее устройство виртуальная таблица обороты

См. также

СКД Механизмы типовых конфигураций Запросы Программист Платформа 1С v8.3 1С:Зарплата и кадры государственного учреждения 3 1С:Зарплата и Управление Персоналом 3.x Россия Бесплатно (free)

Работая с типовыми отчетами в конфигурациях «Зарплата и управление персоналом, редакция 3», «Зарплата и кадры государственного учреждения, редакция 3» и подобных, в схемах компоновки данных можно встретить конструкции запросов, которые обращаются к некоторым виртуальным таблицам.

20.08.2024    1897    PROSTO-1C    0    

18

Механизмы типовых конфигураций Программист Платформа 1С v8.3 1С:Комплексная автоматизация 2.х Россия Бесплатно (free)

Эта ошибка была обнаружена мной в типовой конфигурации 1С:Комплексная автоматизация 2 (2.5.16.115), БСП версия 3.1.9.302. Возникает она после того, как вы добавляете в расширение бизнес-процесс или задачу, выполняете обновление идентификаторов метаданных расширений, но ошибка при записи любого элемента справочника "Профили групп доступа" всё равно остаётся.

01.07.2024    1933    Vidz    0    

11

Механизмы типовых конфигураций Программист Платформа 1С v8.3 Конфигурации 1cv8 Россия Бесплатно (free)

Очень часто в написании кода требуется обращаться к предопределённым значениям. Если идёт обращение к типовым предопределённым значениям, то проблем не возникает.

24.06.2024    1185    olja-ljaaa    0    

3

Механизмы типовых конфигураций Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 Бесплатно (free)

Проблемы при создании ресурсной спецификации. Связь настроек спецификации и настроек структуры заказа в ЕРП 2.5.

06.05.2024    1300    It-digit    1    

2

Механизмы типовых конфигураций Ценообразование, анализ цен Программист Пользователь Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 Россия Абонемент ($m)

Продолжение темы вынесения кусков повторно-используемого кода в запрос. В прошлый раз мы сделали это с вычислением пользовательских формул. Здесь замахнулись на формулы, задаваемые пользователем запросами.

1 стартмани

11.04.2024    1138    tango    5    

3
Оставьте свое сообщение