Работа с данными в 1С:Предприятие часто требует объединения информации из нескольких таблиц — будь то справочники, документы или регистры. Без правильной связи таблиц вы получите либо неполные данные, либо ошибки выполнения. Эта статья поможет разобраться, как грамотно связывать таблицы в 1С 8.3 и 1С 8.2, используя разные типы соединений, виртуальные таблицы и параметры запросов.
Мы рассмотрим не только базовые операции типа INNER JOIN, но и нюансы работы с LEFT JOIN, FULL JOIN, а также покажем, как избежать типичных ошибок при связывании больших объемов данных. Особое внимание уделим оптимизации запросов с соединениями — это критично для производительности в крупных базах.
1. Основные типы соединений таблиц в 1С
В языке запросов 1С поддерживаются все стандартные типы соединений, аналогичные SQL. Их выбор зависит от задачи: нужно ли получить только совпадающие записи, все записи из одной таблицы с дополнением из другой, или же полный набор данных из обеих таблиц.
Рассмотрим ключевые варианты:
- 🔹 ВНУТРЕННЕЕ (INNER JOIN) — возвращает только строки, где есть совпадения в обеих таблицах. Самый частый и быстрый тип соединения.
- 🔸 ЛЕВОЕ (LEFT JOIN) — включает все записи из левой таблицы и соответствующие им данные из правой. Если совпадений нет, поля правой таблицы заполняются
NULL. - 🔶 ПРАВОЕ (RIGHT JOIN) — аналогично левому, но приоритет отдается правой таблице. В 1С используется редко, так как его всегда можно заменить
LEFT JOINс перестановкой таблиц. - 🟣 ПОЛНОЕ (FULL JOIN) — возвращает все строки из обеих таблиц, дополняя отсутствующие данные
NULL. В 1С 8.3 реализовано через комбинациюLEFT JOINиUNION.
Пример базового запроса с INNER JOIN для связывания справочника Номенклатура и документа РеализацияТоваровУслуг:
ВЫБРАТЬ
РеализацияТоваровУслуг.Номенклатура КАК Номенклатура,
РеализацияТоваровУслуг.Количество КАК Количество,
Номенклатура.Наименование КАК Наименование
ИЗ
Документ.РеализацияТоваровУслуг КАК РеализацияТоваровУслуг
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО РеализацияТоваровУслуг.Номенклатура = Номенклатура.Ссылка
⚠️ Внимание: В 1С 8.2 синтаксис соединений строже — нельзя использовать псевдонимы таблиц в условииПОбез явного указания. Например, вместоПО Ссылка = Номенклатуранужно писатьПО Таблица1.Ссылка = Таблица2.Ссылка.
2. Как связать таблицы через виртуальные таблицы
Виртуальные таблицы в 1С — это специальные представления данных регистров накопления, бухгалтерии или расчетов. Они позволяют получать остатки, обороты или движения без написания сложных запросов с группировками. Связь с виртуальными таблицами имеет свои особенности.
Например, чтобы получить остатки товаров на складе с привязкой к номенклатуре, используем виртуальную таблицу РегистрНакопления.ТоварыНаСкладах.Остатки:
ВЫБРАТЬ
Номенклатура.Наименование КАК Товар,
ОстаткиТоваров.КоличествоОстаток КАК Остаток
ИЗ
Справочник.Номенклатура КАК Номенклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(
&ДатаОкончания,
Склад = &Склад
) КАК ОстаткиТоваров
ПО Номенклатура.Ссылка = ОстаткиТоваров.Номенклатура
Обратите внимание на параметры виртуальной таблицы &ДатаОкончания и &Склад — они обязательны для корректной выборки. Без указания склада или даты запрос либо вернет ошибку, либо будет выполняться крайне долго.
Указать все обязательные параметры (дата, измерения)
Проверить права доступа к регистру
Ограничить период выборки для ускорения запроса
Использовать индексированные поля для соединения-->
⚠️ Внимание: Виртуальные таблицы оборотов (например,.Обороты) могут существенно нагружать сервер при больших периодах. Всегда ограничивайте диапазон дат параметром&НачалоПериодаи&КонецПериода.
3. Связь по нескольким полям: составные ключи
Иногда для точного связывания таблиц недостаточно одного поля. Например, в регистре ВзаиморасчетыСКонтрагентами уникальная запись определяется комбинацией Контрагент + Договор + Валюта. В таких случаях используют составные ключи.
Синтаксис соединения по нескольким полям:
ВЫБРАТЬ
Документ.ПоступлениеТоваров.Номер КАК НомерДокумента,
РегистрБухгалтерии.Взаиморасчеты.Сумма КАК СуммаДолга
ИЗ
Документ.ПоступлениеТоваров КАК Документ.ПоступлениеТоваров
ЛЕВОЕ СОЕДИНЕНИЕ РегистрБухгалтерии.Взаиморасчеты КАК РегистрБухгалтерии.Взаиморасчеты
ПО (Документ.ПоступлениеТоваров.Контрагент = РегистрБухгалтерии.Взаиморасчеты.Контрагент)
И (Документ.ПоступлениеТоваров.Договор = РегистрБухгалтерии.Взаиморасчеты.Договор)
И (Документ.ПоступлениеТоваров.ВалютаДокумента = РегистрБухгалтерии.Взаиморасчеты.Валюта)
Ключевые моменты:
- 📌 Условия в скобках
ПО (поле1 = поле1) И (поле2 = поле2)обязательно группировать. - 📌 Порядок полей в условии влияет на производительность — сначала указывайте поля с индексами.
- 📌 Для регистров с большим количеством измерений составные ключи могут замедлить запрос. В таких случаях используйте временные таблицы.
Внутреннее (INNER JOIN)
Левое (LEFT JOIN)
Полное (FULL JOIN)
Не использую соединения-->
4. Связь таблиц с использованием параметров
Параметры в запросах 1С позволяют динамически подставлять значения при выполнении. Это особенно удобно для связывания таблиц, где условия соединения зависят от пользовательского ввода или контекста (например, текущий склад, период, организация).
Пример запроса с параметрами для связи документа ЗаказПокупателя и регистра ЦеныНоменклатуры:
ВЫБРАТЬ
ЗаказПокупателя.Номенклатура КАК Номенклатура,
ЗаказПокупателя.Количество КАК Количество,
ЦеныНоменклатуры.Цена КАК Цена
ИЗ
Документ.ЗаказПокупателя КАК ЗаказПокупателя
ЛЕВОЕ СОЕДИНЕНИЕ РегистрСведений.ЦеныНоменклатуры.СрезПоследних(&ДатаЦены) КАК ЦеныНоменклатуры
ПО (ЗаказПокупателя.Номенклатура = ЦеныНоменклатуры.Номенклатура)
И (ЦеныНоменклатуры.ТипЦен = &ТипЦен)
И (ЦеныНоменклатуры.Организация = &Организация)
Важно:
- 🔧 Параметры обозначаются знаком
&(например,&ДатаЦены). - 🔧 Для дат используйте формат
ГГГГММДД(например,20231231для 31.12.2023). - 🔧 Если параметр не задан, запрос вернет ошибку. Всегда проверяйте передачу параметров перед выполнением.
Для отладки запросов с параметрами используйте конструктор запросов в конфигураторе. Он покажет, какие параметры ожидает запрос, и позволит протестировать их значения без написания кода.
5. Типичные ошибки при связывании таблиц и как их избежать
Даже опытные разработчики 1С сталкиваются с ошибками при работе со связями таблиц. Рассмотрим наиболее распространенные проблемы и способы их решения.
| Ошибка | Причина | Решение |
|---|---|---|
Поле не найдено (Field not found) |
Опечатка в имени поля или таблицы, либо поле не существует в текущей версии конфигурации. | Проверьте имена полей в метаданных (Ctrl+Shift+M в конфигураторе). Используйте автоподстановку в конструкторе запросов. |
Недопустимое соединение таблиц |
Попытка связать таблицы по полям разных типов (например, Ссылка и Строка). |
Приведите поля к одному типу с помощью ВЫРАЗИТЬ или ЗНАЧЕНИЕ. |
| Запрос выполняется слишком долго | Отсутствуют индексы на полях соединения или запрос извлекает слишком много данных. | Добавьте индексы в конфигураторе (Индексировать = Истина). Ограничьте выборку условием ГДЕ. |
| Дублирование строк в результате | Связь "многие ко многим" без группировки или неправильное использование FULL JOIN. |
Используйте РАЗЛИЧНЫЕ или ГРУППИРОВКА ПО для устранения дублей. |
Одна из самых коварных ошибок — неявное преобразование типов. Например, если вы связываете поле типа Число с полем Строка, 1С может автоматически преобразовать данные, но это приведет к непредсказуемым результатам. Всегда следите за типами полей!
Что делать, если запрос с соединением возвращает пустой результат?
1. Проверьте, есть ли данные в исходных таблицах (выполните отдельные запросы к каждой).
2. Убедитесь, что условия соединения (ПО) корректны — возможно, нет совпадающих записей.
3. Проверьте права доступа: у пользователя могут быть ограничения на чтение одной из таблиц.
4. Если используете виртуальные таблицы, проверьте передачу параметров (дата, измерения).
5. Включите трассировку SQL (в конфигураторе: Сервис → Параметры → Трассировка SQL) для анализа выполняемого запроса.
6. Оптимизация запросов со связями таблиц
Производительность запросов с соединениями критична для крупных баз данных. Неоптимизированный запрос может "подвесить" систему на несколько минут. Вот ключевые приемы оптимизации:
- ⚡ Индексируйте поля соединения — в конфигураторе отметьте
Индексировать = Истинадля полей, используемых вПО. - ⚡ Ограничивайте выборку — всегда добавляйте
ГДЕс фильтрами по дате, организации или другим критериям. - ⚡ Используйте временные таблицы — для сложных соединений сначала сохраните промежуточные данные во временную таблицу, а затем связывайте ее с основными.
- ⚡ Избегайте
FULL JOIN— этот тип соединения наиболее ресурсоемкий. Замените его комбинациейLEFT JOINиRIGHT JOINсUNION.
Пример оптимизированного запроса с временной таблицей:
// Сначала сохраняем данные в временную таблицу
ВЫБРАТЬ РАЗЛИЧНЫЕ
Номенклатура.Ссылка КАК Номенклатура
ПОМЕСТИТЬ ВТНоменклатура
ИЗ
Документ.РеализацияТоваровУслуг КАК Реализация
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Номенклатура КАК Номенклатура
ПО Реализация.Номенклатура = Номенклатура.Ссылка
ГДЕ
Реализация.Дата МЕЖДУ &НачалоПериода И &КонецПериода
ИНДЕКСИРОВАТЬ ПО Номенклатура;
// Затем связываем с основной таблицей
ВЫБРАТЬ
ВТНоменклатура.Номенклатура КАК Номенклатура,
Остатки.КоличествоОстаток КАК Остаток
ИЗ
ВТНоменклатура КАК ВТНоменклатура
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&КонецПериода) КАК Остатки
ПО ВТНоменклатура.Номенклатура = Остатки.Номенклатура
⚠️ Внимание: Временные таблицы в 1С хранятся в памяти сервера. Если данных слишком много, это может привести к переполнению памяти. Всегда ограничивайте объем данных, помещаемых во временные таблицы.
Для ускорения запросов с соединениями сначала фильтруйте данные в подзапросах или временных таблицах, а затем связывайте уже отфильтрованные наборы.
7. Связь таблиц в отчетах и системах компоновки данных
В 1С многие отчеты строятся на основе системы компоновки данных (СКД). Здесь связь таблиц настраивается визуально, без написания кода. Однако есть нюансы:
- 📊 В настройках СКД связь между наборами данных устанавливается через параметр
Связь по полям. - 📊 Для связи доступны только поля, выбранные в наборах данных. Если нужно связать по полю, которого нет в выборке, добавьте его в набор.
- 📊 В СКД можно использовать только
INNER JOINиLEFT JOIN. Для других типов соединений потребуется доработка схемы компоновки.
Пример настройки связи в СКД:
- Откройте схему компоновки данных.
- Перейдите на закладку
Наборы данных. - Выделите два набора, которые нужно связать.
- В панели свойств найдите параметр
Связь по полями укажите поля для соединения (например,Номенклатура.Ссылка). - Выберите тип соединения:
ВнутреннееилиЛевое.
Если в отчете не хватает гибкости СКД, можно создать собственный запрос с нужными соединениями и подключить его как набор данных.
FAQ: Частые вопросы по связыванию таблиц в 1С
Можно ли связать таблицы из разных баз данных в одном запросе?
Нет, в стандартном языке запросов 1С нельзя напрямую связывать таблицы из разных баз. Для этого нужно:
- Использовать распределенные информационные базы (РИБ).
- Настроить обмен данными через XML или веб-сервисы.
- Применить внешние источники данных (доступно в 1С:Предприятие 8.3.14+).
В последнем случае можно подключить внешнюю базу как источник и связать ее таблицы с локальными.
Как связать таблицу значений с таблицей базы данных?
Таблицу значений (ТаблицаЗначений) нельзя напрямую связать с таблицей базы в запросе. Решения:
- 🔄 Временная таблица: Загрузите данные из таблицы значений во временную таблицу, затем свяжите ее с основными данными.
- 🔄 Подзапрос: Используйте конструкцию
ВЫБРАТЬ ... ГДЕ Поле В (&СписокЗначений). - 🔄 Обход в цикле: Для небольших объемов данных можно в цикле обращаться к базе для каждой строки таблицы значений (не рекомендуется для больших массивов).
Пример с временной таблицей:
// Загружаем таблицу значений во временную таблицу
ВТСписокНоменклатуры = Новый ВременнаяТаблица;
ВТСписокНоменклатуры.Колонки.Добавить("Номенклатура", Новый ОписаниеТипов("СправочникСсылка.Номенклатура"));
Для Каждого Строка Из ТаблицаЗначений Цикл
ВТСписокНоменклатуры.Добавить();
ВТСписокНоменклатуры.Номенклатура = Строка.Номенклатура;
КонецЦикла;
// Связываем с данными базы
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
ВТСписокНоменклатуры.Номенклатура КАК Номенклатура,
Остатки.КоличествоОстаток КАК Остаток
ИЗ
ВТСписокНоменклатуры КАК ВТСписокНоменклатуры
ЛЕВОЕ СОЕДИНЕНИЕ РегистрНакопления.ТоварыНаСкладах.Остатки(&Дата) КАК Остатки
ПО ВТСписокНоменклатуры.Номенклатура = Остатки.Номенклатура";
Запрос.УстановитьПараметр("Дата", ТекущаяДата());
Запрос.ВременныеТаблицы.Добавить(ВТСписокНоменклатуры);
Почему при связывании таблиц возвращаются дубли строк?
Дубли возникают в двух случаях:
- Связь "многие ко многим": Например, в таблице
Документ.Реализацияодна номенклатура может встречаться несколько раз, и в таблицеРегистрСведений.Ценыдля этой номенклатуры также несколько записей. В результате получается декартово произведение. - Отсутствие уникального ключа: Если связь идет не по уникальному полю (например, по наименованию вместо ссылки), могут совпадать несколько записей.
Решения:
- 🔹 Используйте
РАЗЛИЧНЫЕилиГРУППИРОВКА ПО. - 🔹 Добавьте в условие соединения дополнительные поля для уточнения (например,
ПО Номенклатура = Номенклатура И Организация = Организация). - 🔹 Проверьте структуру данных — возможно, нужно нормализовать таблицы.
Как связать таблицы, если поля для соединения имеют разные типы?
Если поля разных типов (например, Строка и Число), их нужно привести к одному типу с помощью функций:
ВЫРАЗИТЬ(Поле1 КАК Тип)— явно преобразует поле к указанному типу.ЗНАЧЕНИЕ(Поле1)— преобразует значение к типу по умолчанию.СТРОКА(Поле1)илиЧИСЛО(Поле1)— преобразует к строковому или числовому типу.
Пример:
ВЫБРАТЬ
Таблица1.Код КАК Код,
Таблица2.Наименование КАК Наименование
ИЗ
Документ.Таблица1 КАК Таблица1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Справочник.Таблица2 КАК Таблица2
ПО ВЫРАЗИТЬ(Таблица1.Код КАК Строка) = Таблица2.КодСтроковый
Осторожно: неявное преобразование типов может работать непредсказуемо. Например, сравнение числа 123 и строки "000123" вернет Ложь, если не привести их к одному типу.
Можно ли в 1С использовать соединение более чем двух таблиц?
Да, в 1С можно связывать любое количество таблиц в одном запросе. Синтаксис аналогичен SQL:
ВЫБРАТЬ
Таблица1.Поле1,
Таблица2.Поле2,
Таблица3.Поле3
ИЗ
Таблица1 КАК Таблица1
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таблица2 КАК Таблица2
ПО Таблица1.Ключ = Таблица2.Ключ
ВНУТРЕННЕЕ СОЕДИНЕНИЕ Таблица3 КАК Таблица3
ПО Таблица2.Ссылка = Таблица3.Ссылка
Рекомендации:
- 📌 Связывайте таблицы последовательно: сначала две, затем результат с третьей и т.д.
- 📌 Для более чем 3-4 таблиц рассмотрите возможность разбиения запроса на несколько этапов с использованием временных таблиц.
- 📌 Следите за производительностью — каждое дополнительное соединение увеличивает время выполнения.