При попытке расширить функциональность справочника, добавив в него данные из регистра сведений через ДинамическийСписок, многие разработчики сталкиваются с критической ошибкой: «Обнаружено дублирование ключевых значений в колонках: "Ссылка"». Давайте разберем, почему это происходит и как правильно решить данную задачу.
Ошибка возникает из-за фундаментального принципа работы ДинамическогоСписка в 1С. Этот объект жестко привязан к «основной таблице» (в нашем случае — справочнику). Для корректной работы платформы каждой записи в списке должна соответствовать ровно одна строка в результирующей выборке запроса.
Когда вы выполняете ЛЕВОЕ СОЕДИНЕНИЕ со справочником, а в регистре сведений для одного элемента номенклатуры существует несколько записей (например, по количеству характеристик или наборов свойств), запрос «размножает» строки. В результате для одной ссылки на справочник получается несколько строк с разными данными, что и приводит к дублированию ключа.
Если ваша задача — вывести в список хотя бы одну актуальную цену (например, максимальную или минимальную), необходимо свернуть данные регистра до одной записи на каждый элемент справочника. Для этого мы применим агрегатные функции и группировку.
Рассмотрим вариант запроса, который позволяет избежать дублей:
ВЫБРАТЬ
СправочникСамокаты.Ссылка КАК Ссылка,
СправочникСамокаты.Наименование КАК Наименование,
МАКСИМУМ(ЦеныНоменклатурыСрезПоследних.Цена) КАК Цена
ИЗ
Справочник.Самокаты КАК СправочникСамокаты
ЛЕВОЕ СОЕДИНЕНИЕ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ТипЦен = &ТипЦен) КАК ЦеныНоменклатурыСрезПоследних
ПО
ЦеныНоменклатурыСрезПоследних.Номенклатура = СправочникСамокаты.Ссылка
СГРУППИРОВАТЬ ПО
СправочникСамокаты.Ссылка,
СправочникСамокаты.Наименование
Использование СГРУППИРОВАТЬ ПО гарантирует, что для каждой ссылки справочника в итоговой выборке останется только одна строка, что полностью устраняет ошибку дублирования.
Более профессиональным и чистым подходом считается использование вложенного запроса. Мы сначала готовим данные в регистре, группируя их по номенклатуре, и только потом присоединяем этот результат к основному справочнику.
ВЫБРАТЬ
Спр.Ссылка КАК Ссылка,
Спр.Наименование КАК Наименование,
Рег.Цена КАК Цена
ИЗ
Справочник.Самокаты КАК Спр
ЛЕВОЕ СОЕДИНЕНИЕ
(ВЫБРАТЬ
РегСрез.Номенклатура КАК Номенклатура,
МАКСИМУМ(РегСрез.Цена) КАК Цена
ИЗ
РегистрСведений.ЦеныНоменклатуры.СрезПоследних(, ТипЦен = &ТипЦен) КАК РегСрез
СГРУППИРОВАТЬ ПО
РегСрез.Номенклатура) КАК Рег
ПО
Спр.Ссылка = Рег.Номенклатура
Этот метод предпочтительнее, так как он делает структуру запроса логически понятной: сначала мы получаем уникальные цены для каждого товара, а затем просто «подтягиваем» их к списку справочника.
Часто разработчики пытаются решить проблему, просто удаляя поле НаборСвойств из запроса. Однако, если в самом регистре сведений физически хранится несколько записей для одной номенклатуры (даже если они визуально не выводятся), ЛЕВОЕ СОЕДИНЕНИЕ всё равно вернет несколько строк. Платформа видит, что количество записей превышает количество ссылок, и снова выдает ошибку. Помните: изменение набора выводимых полей не влияет на количество строк, возвращаемых запросом, если нет группировки или условий отбора.
Если бизнес-требования предполагают, что пользователь должен видеть цены по всем наборам свойств одновременно для одного товара в одной строке, ДинамическийСписок для этого не предназначен. В таких случаях мы рекомендуем:
ТаблицаЗначений или ДинамическийСписок с другой логикой).ПриАктивизацииСтроки основного списка, фильтруя данные по выбранному товару.Применяя эти методы, вы сможете корректно отображать данные в 1С, избегая ошибок дублирования и обеспечивая стабильную работу пользовательского интерфейса.