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