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