Как объединить данные нескольких записей в одну строку в запросе 1С?

Программист 1С v8.3 (Управляемые формы) 1С:Управление торговлей Управленческий учет Торговля и дистрибуция
← На главную

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

Метод пакетных запросов с нумерацией (использование АВТОНОМЕРЗАПИСИ)

Рассмотрим один из самых гибких способов объединения строк без использования дополнительных регистров. Суть метода заключается в том, чтобы сначала пронумеровать записи внутри каждой группы (номенклатуры), а затем сгруппировать их, распределив по отдельным колонкам.

Для начала создадим временную таблицу со всеми записями. Далее, используя функцию АВТОНОМЕРЗАПИСИ() или логическое соединение, присвоим каждой ячейке порядковый номер. После этого мы используем конструкцию ВЫБОР КОГДА для того, чтобы разложить данные по колонкам Ячейка1, Ячейка2 и так далее.

Посмотрим на пример реализации такого запроса:


ВЫБРАТЬ
	Размещение.Номенклатура КАК Номенклатура,
	Размещение.Ячейка.Наименование КАК Ячейка
ПОМЕСТИТЬ ВсеЯчейки
ИЗ
	РегистрСведений.РазмещениеНоменклатурыПоСкладскимЯчейкам КАК Размещение
;

ВЫБРАТЬ
	Т1.Номенклатура КАК Номенклатура,
	Т1.Ячейка КАК Ячейка,
	КОЛИЧЕСТВО(РАЗЛИЧНЫЕ Т2.Ячейка) КАК НомерПП
ПОМЕСТИТЬ ЯчейкиСНомерами
ИЗ
	ВсеЯчейки КАК Т1
		ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВсеЯчейки КАК Т2
		ПО Т1.Номенклатура = Т2.Номенклатура
			И Т1.Ячейка <= Т2.Ячейка
СГРУППИРОВАТЬ ПО
	Т1.Номенклатура, Т1.Ячейка
;

ВЫБРАТЬ
	Т.Номенклатура КАК Номенклатура,
	МАКСИМУМ(ВЫБОР КОГДА Т.НомерПП = 1 ТОГДА Т.Ячейка ИНАЧЕ NULL КОНЕЦ) КАК Ячейка1,
	МАКСИМУМ(ВЫБОР КОГДА Т.НомерПП = 2 ТОГДА Т.Ячейка ИНАЧЕ NULL КОНЕЦ) КАК Ячейка2,
	МАКСИМУМ(ВЫБОР КОГДА Т.НомерПП = 3 ТОГДА Т.Ячейка ИНАЧЕ NULL КОНЕЦ) КАК Ячейка3
ПОМЕСТИТЬ ИтоговыеКолонки
ИЗ
	ЯчейкиСНомерами КАК Т
СГРУППИРОВАТЬ ПО
	Т.Номенклатура
;

ВЫБРАТЬ
	Т.Номенклатура,
	ЕСТЬNULL(Т.Ячейка1, "") + ", " + ЕСТЬNULL(Т.Ячейка2, "") + ", " + ЕСТЬNULL(Т.Ячейка3, "") КАК СтрокаЯчеек
ИЗ
	ИтоговыеКолонки КАК Т

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

Преимущества и недостатки использования в Динамическом списке

Использование таких сложных запросов внутри Динамического списка — это компромиссное решение. Рассмотрим плюсы и минусы:

  1. Производительность: Запрос выполняется на сервере БД при каждой прокрутке списка. При больших объемах данных это может вызвать замедление интерфейса.
  2. Простота реализации: Вам не нужно создавать дополнительные структуры данных, все собирается «на лету» средствами платформы.
  3. Ограничения СУБД: При включенном RLS сложные соединения могут существенно нагружать сервер, что приведет к блокировкам.

Рекомендуемый «архитектурный» подход: Пре-агрегация

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

  1. Создайте дополнительный Регистр сведений, который будет хранить уже готовую строку (результат конкатенации).
  2. В модуле набора записей основного регистра используйте событие ПриЗаписи.
  3. Внутри обработчика вычислите актуальный список ячеек, объедините их в строку с помощью функции СтрСоединить и запишите в ваш вспомогательный регистр.
  4. В запросе Динамического списка просто сделайте ЛЕВОЕ СОЕДИНЕНИЕ с этим вспомогательным регистром.

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

Заключение

Мы проанализировали ситуацию и выяснили, что выбор решения зависит от требований к производительности. Для небольших баз или разовых отчетов вполне допустимо использовать пакетные запросы с нумерацией строк. Однако, если вы работаете над крупной системой с высокой интенсивностью обращений пользователей, единственно верным решением будет вычисление и хранение итоговой строки в отдельном объекте данных (регистре), чтобы избежать лишней нагрузки на SQL-сервер при каждом обновлении списка.

← На главную