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