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