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