Как составить запрос в 1С для отбора клиентов по количеству разовых покупок и общему лимиту?

Программист 1С v8.3 (Обычные формы) Управленческий учет Торговля и дистрибуция
← На главную

В практике программирования на платформе 1С часто возникают задачи, когда необходимо проанализировать поведение клиентов на основе специфических условий закупа. Например, нас могут интересовать не все продажи, а только те, где товар приобретался строго в количестве одной единицы за раз. При этом важно не просто найти такие продажи, но и ограничить итоговую выборку суммарным количеством этих "единичных" покупок за период. Рассмотрим подробно, как реализовать такую логику с помощью языка запросов 1С.

Разбор базовой логики запроса

Для решения поставленной задачи нам необходимо выполнить три последовательных шага в рамках одного запроса:

  1. Фильтрация на уровне записей: Выбираем только те строки из регистров, где поле Количество равно 1.
  2. Группировка данных: Схлопываем данные по клиентам (контрагентам) и товарам (номенклатуре), чтобы подсчитать общую сумму.
  3. Фильтрация на уровне итогов: Отсекаем тех клиентов, у которых накопленная сумма "единичных" покупок превышает заданный лимит (например, 50 банок).

Проанализируем пример кода, который решает эту задачу. Основная хитрость заключается в правильном использовании секций ГДЕ и ИМЕЮЩИЕ.


ВЫБРАТЬ
    Продажи.Контрагент КАК Клиент,
    Продажи.Номенклатура КАК Товар,
    СУММА(Продажи.Количество) КАК ОбщееКоличество
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Количество = 1
    И Продажи.Период МЕЖДУ &ДатаНачала И &ДатаОкончания
СГРУППИРОВАТЬ ПО
    Продажи.Контрагент,
    Продажи.Номенклатура
ИМЕЮЩИЕ
    СУММА(Продажи.Количество) <= 50

В данном примере условие ГДЕ Продажи.Количество = 1 работает как первичный фильтр: система "выбрасывает" из обработки все строки, где за один раз было куплено 2, 3 или более единиц товара. Только после этого оставшиеся "единички" суммируются, и условие ИМЕЮЩИЕ проверяет, чтобы итоговый результат не превысил порог.

Нюансы работы с физическими таблицами и производительностью

Рассмотрим ситуацию с точки зрения производительности системы. В приведенном выше примере мы обращаемся к основной таблице регистра (физической таблице). Это оправдано, так как нам нужно анализировать каждую конкретную запись на предмет равенства количества единице. Виртуальные таблицы (например, Обороты) здесь не подойдут, так как они выдают уже сгруппированные данные, и мы потеряем информацию о том, была ли это одна покупка на 10 единиц или 10 покупок по 1 единице.

Однако при работе с физическими таблицами важно помнить о следующих моментах:

Сложный случай: проверка уникальности всей покупки

Иногда под "покупкой в единственном числе" подразумевается не просто строка в документе, а весь чек целиком. То есть нас интересуют ситуации, когда клиент купил только одну единицу одного товара и больше ничего в этом документе нет. В этом случае простого условия Количество = 1 будет недостаточно.

Выясним, как решить такую задачу. Нам потребуется вложенный запрос или временная таблица, чтобы сначала определить список "чистых" документов (где всего 1 строка и количество в ней равно 1).


// Шаг 1: Отбираем регистраторы, где только одна строка и количество = 1
ВЫБРАТЬ
    Продажи.Регистратор
ПОМЕСТИТЬ ВТ_ОдиночныеПродажи
ИЗ
    РегистрНакопления.Продажи КАК Продажи
СГРУППИРОВАТЬ ПО
    Продажи.Регистратор
ИМЕЮЩИЕ
    КОЛИЧЕСТВО(Продажи.НомерСтроки) = 1
    И СУММА(Продажи.Количество) = 1
;

// Шаг 2: Получаем итоговые данные по этим регистраторам
ВЫБРАТЬ
    Продажи.Контрагент,
    СУММА(Продажи.Количество) КАК Итого
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Регистратор В (ВЫБРАТЬ ВТ.Регистратор ИЗ ВТ_ОдиночныеПродажи КАК ВТ)
СГРУППИРОВАТЬ ПО
    Продажи.Контрагент
ИМЕЮЩИЕ
    СУММА(Продажи.Количество) <= 50

Учет характеристик и упаковок

Проанализируем ситуацию, когда в базе ведется учет в различных единицах измерения или по характеристикам. Если клиент купил "1 упаковку", в которой 20 банок пива, поле Количество в регистре может быть равно 1, если оно хранит данные в единицах отчетов, или 20, если в базовых единицах.

Важный совет: Всегда проверяйте, в каких единицах хранятся данные в вашем регистре. Если вы используете поле Количество, убедитесь, что это именно физические единицы (штуки/банки). Если учет ведется в упаковках, условие должно выглядеть так:

ГДЕ Продажи.Количество * Продажи.Коэффициент = 1

Применение временных таблиц для оптимизации

Если отчет строится за большой период и данных очень много, использование секции ИМЕЮЩИЕ на лету может быть медленным. Рассмотрим более профессиональный подход с использованием временных таблиц. Это позволит СУБД лучше оптимизировать план запроса.


ВЫБРАТЬ
    Продажи.Контрагент КАК Клиент,
    СУММА(Продажи.Количество) КАК СуммаЕдиничныхПокупок
ПОМЕСТИТЬ ВТ_Агрегация
ИЗ
    РегистрНакопления.Продажи КАК Продажи
ГДЕ
    Продажи.Количество = 1
    И Продажи.Период МЕЖДУ &Начало И &Конец
СГРУППИРОВАТЬ ПО
    Продажи.Контрагент
;

ВЫБРАТЬ
    ВТ.Клиент,
    ВТ.СуммаЕдиничныхПокупок
ИЗ
    ВТ_Агрегация КАК ВТ
ГДЕ
    ВТ.СуммаЕдиничныхПокупок <= 50

Посмотрим, что мы сделали: сначала мы собрали все подходящие продажи во временную таблицу ВТ_Агрегация, просуммировали их, а затем вторым простым запросом отсекли лишнее. Такой подход считается эталонным при разработке сложных отчетов в 1С.

Итоги

Подведем итог нашему исследованию. Для реализации условия "разовые покупки по 1 шт, суммарно не более 50" в 1С необходимо:

Используя эти методы, вы сможете гибко настраивать аналитические отчеты и выявлять специфические группы контрагентов, основываясь на их покупательских привычках.

← На главную