Что означает ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО Истина в запросах 1С и для чего оно применяется?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

Разработчики, которые часто пишут сложные отчеты или занимаются доработкой типовых конфигураций (таких как «1С:Зарплата и управление персоналом» или «1С:ERP»), рано или поздно сталкиваются в чужом коде с весьма загадочной конструкцией: ВНУТРЕННЕЕ СОЕДИНЕНИЕ ... ПО ИСТИНА. С первого взгляда такое условие связи кажется лишенным практического смысла. Ведь мы привыкли соединять таблицы по конкретным ключевым полям — идентификаторам, ссылкам, кодам или датам. Условие вида ПО ИСТИНА полностью игнорирует сопоставление полей.

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

Физический смысл соединения: Декартово произведение (CROSS JOIN)

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

В языке запросов «1С» нет прямого оператора CROSS JOIN. Чтобы получить аналогичный результат, разработчики используют стандартное соединение, но вместо равенства ключевых полей (например, Таблица1.Ссылка = Таблица2.Ссылка) указывают тождественно истинное условие — логическую константу ИСТИНА (или TRUE на уровне СУБД).

Давайте проанализируем, как это работает. При обычном соединении СУБД проверяет каждую строку на соответствие условию. Если условие выполняется, строка попадает в выборку. Когда мы пишем ПО ИСТИНА, это условие выполняется абсолютно для любой пары строк из двух таблиц. В результате каждая запись из первой таблицы будет сопоставлена со всеми без исключения записями из второй таблицы.

Если в Таблице 1 содержится N строк, а в Таблице 2 — M строк, то на выходе мы гарантированно получим таблицу размером N * M строк.

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

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

Таблица 1 (Товары)

Наим id
Товар 1 21
Товар 2 22
Товар 3 23
Товар 1 21

Таблица 2 (Заказчики)

Наим id
Заказчик 2 22
Заказчик 3 23
Заказчик 1 21

Напишем следующий запрос на языке 1С:


ВЫБРАТЬ
	Товары.Наим КАК ТоварНаим,
	Товары.id КАК ТоварID,
	Заказчики.Наим КАК ЗаказчикНаим,
	Заказчики.id КАК ЗаказчикID
ИЗ
	ТаблицаТовары КАК Товары
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ТаблицаЗаказчики КАК Заказчики
		ПО ИСТИНА

Давайте выясним, что произойдет при выполнении этого запроса. Обратите внимание: поля id в условии соединения никак не участвуют! Платформа полностью проигнорирует тот факт, что у нас есть совпадающие или несовпадающие идентификаторы. Каждая строка из таблицы «Товары» соединится с каждой строкой таблицы «Заказчики».

В результате мы получим таблицу из 12 строк (4 строки товаров * 3 строки заказчиков):

ТоварНаим ТоварID ЗаказчикНаим ЗаказчикID
Товар 1 21 Заказчик 2 22
Товар 1 21 Заказчик 3 23
Товар 1 21 Заказчик 1 21
Товар 2 22 Заказчик 2 22
Товар 2 22 Заказчик 3 23
Товар 2 22 Заказчик 1 21
Товар 3 23 Заказчик 2 22
Товар 3 23 Заказчик 3 23
Товар 3 23 Заказчик 1 21
Товар 1 21 Заказчик 2 22
Товар 1 21 Заказчик 3 23
Товар 1 21 Заказчик 1 21

Как мы видим, результатом стала полная сетка возможных комбинаций строк первой и второй таблиц. Повторяющаяся строка «Товар 1» с ID 21 также послушно размножилась трижды.

Различия ЛЕВОГО, ВНУТРЕННЕГО и ПОЛНОГО соединений ПО ИСТИНА

Очень важно понимать разницу в поведении системы при использовании различных типов соединений с условием ПО ИСТИНА. Особенно ярко эта разница проявляется в ситуациях, когда одна из соединяемых таблиц оказывается пустой. Рассмотрим эти сценарии подробнее.

  1. ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО ИСТИНА.
    Если одна из таблиц пуста (содержит 0 строк), результат всего запроса будет содержать ровно 0 строк. Это логично, поскольку СУБД пытается найти пары для строк первой таблицы во второй таблице, а пар нет. Умножение любого числа строк на ноль дает ноль.
  2. ЛЕВОЕ СОЕДИНЕНИЕ ПО ИСТИНА.
    Если правая таблица пуста, запрос вернет все строки левой таблицы. При этом поля правой таблицы в результирующей выборке примут значение NULL. Если же в правой таблице есть хотя бы одна строка, то левое соединение отработает точно так же, как и внутреннее, то есть перемножит все строки.
  3. ПОЛНОЕ СОЕДИНЕНИЕ ПО ИСТИНА.
    Поведение аналогично левому соединению, но защищает обе таблицы. Если одна из них пуста, вы всё равно получите строки из заполненной таблицы. Интересный лайфхак: если вы гарантированно знаете, что в обеих таблицах содержится строго по одной строке (например, это таблицы свернутых итогов или параметров), то полное соединение ПО ИСТИНА склеит эти строки в одну широкую строку без риска потерять данные, если какая-то из таблиц вдруг окажется пустой.

Реальные сценарии применения в конфигурациях 1С

На первый взгляд декартово произведение кажется искусственным приемом, который редко нужен в реальной жизни. Однако в типовых конфигурациях «1С:Предприятие» эта конструкция используется регулярно. Рассмотрим основные кейсы.

Сценарий 1. Ценообразование по географическим зонам

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

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

Сценарий 2. Построение отчетов и матриц времени (ЗУП)

В конфигурации «1С:Зарплата и управление персоналом» часто требуется построить плоский отчёт по сотрудникам за каждый день расчетного периода, даже если по сотруднику в этот день не было никаких кадровых событий или начислений (например, для вывода пустой строки или анализа прогулов). Для этого используется соединение таблицы уникальных сотрудников с производственным календарем (или списком дат периода) ПО ИСТИНА.

В результате мы получаем готовую координатную сетку «Сотрудник — Дата», которую затем левым соединением связываем с фактическими данными о начислениях и отработанном времени. Это позволяет избежать «дыр» в отчете и вывести красивые графики с нулевыми показателями.

Сценарий 3. Динамическое построение текстов запросов (Шаблонизация)

Разработчики типовых решений часто прибегают к конструкции ПО ИСТИНА для упрощения алгоритмов динамической сборки текста запроса с помощью функции СтрЗаменить().

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


ИЗ
	Таблица1 КАК Т1
	ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таблица2 КАК Т2
	ПО ИСТИНА

То в коде общего модуля мы сможем очень легко дописывать дополнительные фильтры через простой оператор И, не заботясь о том, является ли это условие первым. Мы просто пишем:

ТекстЗапроса = ТекстЗапроса + " И Т1.Организация = Т2.Организация";

Итоговый текст запроса примет вид ПО ИСТИНА И Т1.Организация = Т2.Организация. С точки зрения синтаксиса и оптимизатора СУБД такой запрос абсолютно валиден и будет выполнен корректно, при этом разработчику не пришлось писать сложные проверки на предмет того, нужно ли вставлять ключевое слово ПО или И.

Сценарий 4. Использование в механизмах RLS (ограничение доступа)

В шаблонах ограничений доступа на уровне записей (RLS) конструкция ПО (ИСТИНА) встречается постоянно. Она используется для связи основной таблицы данных (например, физических лиц или документов) с плоскими таблицами разрешенных пользователю значений (групп доступа, подразделений). Если пользователю разрешен доступ к определенной группе, условие связи выполняется, и строка становится доступной для чтения.

Альтернативный синтаксис: Соединение через запятую

В языке запросов «1С» декартово произведение можно получить и другим способом — просто перечислив таблицы в секции ИЗ через запятую:


ВЫБРАТЬ
	Т1.Поле1,
	Т2.Поле2
ИЗ
	Таблица1 КАК Т1,
	Таблица2 КАК Т2

Этот синтаксис пришел из старых стандартов SQL. Результат выполнения этого запроса будет абсолютно идентичен результату запроса с ВНУТРЕННЕЕ СОЕДИНЕНИЕ ПО ИСТИНА. Однако явное использование оператора соединения ПО ИСТИНА считается более предпочтительным по следующим причинам:

Проблемы производительности и СУБД

Внимание! Операция декартова произведения — одна из самых ресурсоемких операций в реляционных базах данных. С точки зрения производительности СУБД (будь то MS SQL, PostgreSQL или IBM DB2), соединение по константе ИСТИНА заставляет оптимизатор использовать физический оператор Nested Loops (Вложенные циклы).

При этом алгоритме СУБД берет каждую строку из первой таблицы и полностью сканирует вторую таблицу для поиска совпадений. Так как условием выступает ИСТИНА, СУБД вынуждена прочитать и сопоставить абсолютно все записи.

Проанализируем риски:

Такой запрос гарантированно приведет к следующим последствиям:

  1. Мгновенный рост нагрузки на процессор сервера СУБД до 100%.
  2. Переполнение дискового пространства временных таблиц (TempDB в MS SQL) из-за попытки сохранить гигантский объем промежуточных данных.
  3. Длительные транзакционные блокировки таблиц, что парализует работу всех остальных пользователей системы.
  4. Аварийное завершение сеанса работы пользователя по таймауту.

Золотое правило разработчика 1С: Использовать конструкцию ПО ИСТИНА можно только в тех случаях, когда вы гарантированно уверены, что хотя бы одна из соединяемых таблиц содержит минимальное количество строк (оптимально — до 10-50 строк). Никогда не соединяйте таким образом две динамически растущие таблицы базы данных.

Резюме

Конструкция ВНУТРЕННЕЕ СОЕДИНЕНИЕ ... ПО ИСТИНА — это мощный и удобный инструмент языка запросов 1С для получения декартова произведения (полной сетки комбинаций строк). Она незаменима при автоматическом формировании расписаний, матриц цен, кадровых календарей и при динамической сборке текстов запросов программными методами. Однако этот инструмент требует от разработчика высокой культуры программирования и четкого понимания объемов данных, которые будут обрабатываться в процессе выполнения запроса.

← На главную