Сгруппировать свои продажи: суммы, среднее и ИМЕЮЩИЕ

Учебные задачи

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

Где и как запускать

Полный серверный общий модуль учебной базы. Собственные значения в памяти, без чтения или записи рабочих данных.

Подготовка

  1. В отдельной учебной базе 8.5.1.1343 создайте общий модуль УчебныйЯзык: Сервер=Истина, Глобальный=Ложь, ВызовСервера=Ложь, Привилегированный=Ложь. Клиентские и внешнее соединение отключены; ПовторноеИспользованиеВозвращаемыхЗначений=НеИспользовать.

  2. Вставьте весь приведённый текст в этот общий модуль. ВыполнитьПример — экспортная точка входа; остальные процедуры и функции располагаются рядом, а не внутри неё.

  3. В своей внешней учебной обработке создайте управляемую форму, команду Выполнить и кнопку. Клиентский обработчик Выполнить(Команда) вызывает свою процедуру ВыполнитьНаСервере(); она имеет директиву &НаСервереБезКонтекста и одну строку УчебныйЯзык.ВыполнитьПример();. Это серверный вызов общего модуля, а не разрешение клиенту прямо обращаться к серверной библиотеке.

  4. Все товары, количества и строки придуманы в этом модуле. Запись документов, подключение к чужой базе, файлы, сеть и печать не используются. В рабочие общие модули текст не вставляйте.

  5. HTML только показывает BSL. Код в 1С не запускался; перечисленные результаты и отрицательные опыты проверяйте самостоятельно в собственном стенде.

Процедура ВыполнитьПример() Экспорт
    Источник = Новый ТаблицаЗначений;
    Источник.Колонки.Добавить("Магазин", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(20)));
    Источник.Колонки.Добавить("Товар", Новый ОписаниеТипов("Строка", , Новый КвалификаторыСтроки(20)));
    Источник.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(5, 0, ДопустимыйЗнак.Неотрицательный)));
    Источник.Колонки.Добавить("Цена", Новый ОписаниеТипов("Число", Новый КвалификаторыЧисла(10, 2, ДопустимыйЗнак.Неотрицательный)));
    Данные = Новый Массив;
    Данные.Добавить(Новый Структура("Магазин,Товар,Количество,Цена", "Север", "Книга", 3, 250));
    Данные.Добавить(Новый Структура("Магазин,Товар,Количество,Цена", "Север", "Ручка", 1, 50));
    Данные.Добавить(Новый Структура("Магазин,Товар,Количество,Цена", "Юг", "Книга", 2, 250));
    Данные.Добавить(Новый Структура("Магазин,Товар,Количество,Цена", "Юг", "Книга", 1, 300));
    Для Каждого Продажа Из Данные Цикл
        СтрокаИсточника = Источник.Добавить();
        СтрокаИсточника.Магазин = Продажа.Магазин;
        СтрокаИсточника.Товар = Продажа.Товар;
        СтрокаИсточника.Количество = Продажа.Количество;
        СтрокаИсточника.Цена = Продажа.Цена;
    КонецЦикла;
    Если Источник.Количество() <> 4 Или Источник.Итог("Количество") <> 7 Тогда
        ВызватьИсключение "Изменились собственные учебные продажи";
    КонецЕсли;
    Менеджер = Новый МенеджерВременныхТаблиц;
    Попытка
        Создание = Новый Запрос;
        Создание.МенеджерВременныхТаблиц = Менеджер;
        Создание.Текст = "ВЫБРАТЬ
        |    Продажи.Магазин КАК Магазин,
        |    Продажи.Товар КАК Товар,
        |    Продажи.Количество КАК Количество,
        |    Продажи.Цена КАК Цена,
        |    Продажи.Количество * Продажи.Цена КАК Сумма
        |ПОМЕСТИТЬ ВТСобственныеПродажи
        |ИЗ &Источник КАК Продажи";
        Создание.УстановитьПараметр("Источник", Источник);
        Создание.Выполнить();
        Запрос = Новый Запрос;
        Запрос.МенеджерВременныхТаблиц = Менеджер;
        Запрос.Текст = "ВЫБРАТЬ
        |    Продажи.Магазин КАК Магазин,
        |    КОЛИЧЕСТВО(*) КАК СтрокПродаж,
        |    СУММА(Продажи.Количество) КАК Единиц,
        |    СУММА(Продажи.Сумма) КАК Сумма,
        |    МИНИМУМ(Продажи.Цена) КАК МинимальнаяЦена,
        |    МАКСИМУМ(Продажи.Цена) КАК МаксимальнаяЦена,
        |    СРЕДНЕЕ(Продажи.Цена) КАК СредняяЦенаСтрок
        |ИЗ ВТСобственныеПродажи КАК Продажи
        |СГРУППИРОВАТЬ ПО Продажи.Магазин";
        Группы = Запрос.Выполнить().Выгрузить();
        Если Группы.Количество() <> 2 Тогда
            ВызватьИсключение "Ожидались два своих магазина";
        КонецЕсли;
        Север = Группы.Найти("Север", "Магазин");
        Юг = Группы.Найти("Юг", "Магазин");
        Если Север = Неопределено Или Юг = Неопределено Тогда
            ВызватьИсключение "Изменились названия учебных магазинов";
        КонецЕсли;
        Сообщить(Север.СтрокПродаж = 2 И Север.Единиц = 4 И Север.Сумма = 800);
        Сообщить(Юг.СтрокПродаж = 2 И Юг.Единиц = 3 И Юг.Сумма = 800);
        Сообщить(Север.МинимальнаяЦена = 50 И Север.МаксимальнаяЦена = 250 И Север.СредняяЦенаСтрок = 150);
        Сообщить(Юг.МинимальнаяЦена = 250 И Юг.МаксимальнаяЦена = 300 И Юг.СредняяЦенаСтрок = 275);
        Сообщить(Север.Сумма / Север.Единиц = 200);
        Сообщить(Окр(Юг.Сумма / Юг.Единиц, 2) = 266.67);
        Запрос.Текст = "ВЫБРАТЬ
        |    Продажи.Магазин КАК Магазин,
        |    СУММА(Продажи.Сумма) КАК Сумма
        |ИЗ ВТСобственныеПродажи КАК Продажи
        |ГДЕ Продажи.Цена >= &МинимальнаяЦена
        |СГРУППИРОВАТЬ ПО Продажи.Магазин
        |ИМЕЮЩИЕ СУММА(Продажи.Сумма) > &ПорогГруппы";
        Запрос.УстановитьПараметр("МинимальнаяЦена", 100);
        Запрос.УстановитьПараметр("ПорогГруппы", 780);
        Отобранные = Запрос.Выполнить().Выгрузить();
        Если Отобранные.Количество() <> 1 Тогда
            ВызватьИсключение "После двух разных отборов ожидалась одна группа";
        КонецЕсли;
        Сообщить(Отобранные[0].Магазин = "Юг" И Отобранные[0].Сумма = 800);
        Сообщить(Источник.Количество() = 4 И Источник.Итог("Количество") = 7);
    Исключение
        Менеджер.Закрыть();
        ВызватьИсключение;
    КонецПопытки;
    Менеджер.Закрыть();
КонецПроцедуры

Разбор по шагам

  1. Создать четыре типизированные строки в памяти: Север/Книга 3×250, Север/Ручка 1×50, Юг/Книга 2×250 и Юг/Книга 1×300. Источник содержит четыре строки, семь единиц и сумму 1600.

  2. ПОМЕСТИТЬ создаёт свою временную таблицу с вычисленной Сумма. Все последующие запросы используют тот же МенеджерВременныхТаблиц, не чужую сессию.

  3. СГРУППИРОВАТЬ ПО Магазин сворачивает четыре исходные строки до двух. Поле магазина входит в группировку; остальные выбранные поля вычисляются агрегатами.

  4. КОЛИЧЕСТВО(*) считает две строки на магазин, СУММА(Количество) — четыре и три единицы, СУММА(Сумма) — по 800. Одинаковая сумма не означает одинаковое число проданных единиц.

  5. МИНИМУМ и МАКСИМУМ берут цену строки. СРЕДНЕЕ(Цена) даёт 150/275 без весов количества, а отношение суммы продаж к единицам — 200/266.67 после округления.

  6. Второй запрос сначала применяет ГДЕ Цена>=100: убирается ручка за 50, и сумма Севера становится 750. Только после группировки ИМЕЮЩИЕ СУММА(Сумма)>780 оставляет Юг с 800.

  7. Найти проверяется на Неопределено до обращения к колонкам. Менеджер закрывается и при ошибке, и после нормального завершения; первоначальная таблица не меняется.

Как проверить результат

  1. Восемь конечных контрольных сообщений Истина. Два сообщения про цены относятся к простому среднему, два последующих — к взвешенной цене.

  2. При пороге группы 800 и строгом > результат второго запроса пуст: 800 не больше 800. Изменив условие на >=, получите другое правило отбора.

  3. Для самостоятельного опыта увеличьте количество северной книги до 4 и пересчитайте ожидания. Не меняйте проверки механически: СРЕДНЕЕ(Цена) остаётся 150, взвешенная цена меняется.

Ожидаемый результат

Две собственные магазинные группы рассчитаны и проверены, а построчный отбор отделён от отбора агрегированных групп.

На что обратить внимание

  1. Нельзя использовать СУММА в ГДЕ вместо ИМЕЮЩИЕ. Условие ИМЕЮЩИЕ использует агрегаты или поля группировки.

  2. СРЕДНЕЕ(Цена) не является средней ценой проданной единицы, если количества строк различаются. Назовите показатель прежде, чем выбирать формулу.

  3. Строки после группировки — не исходные продажи. СУММА сумм, сгруппированных только по магазину, здесь 1600, но повторно присоединённые данные могут дать задвоение.

  4. Нет обращения к рабочим документам. Никакое число из этого учебного источника не является показателем вашей КА2/УНФ/УТ.

  5. Тексты запросов сверены со справкой; выполнения в 1С не было. Ожидания нужно проверить на собственном стенде.

Пример не запускался в вашей базе. Перед применением проверьте его в указанном учебном контексте.

Не хотите разбираться сами?

Адаптируем это решение под вашу базу. Оценка бесплатно.

Оставить задачу

1С, 1С:Предприятие — товарные знаки ООО «1С». Сайт не является официальным представительством фирмы «1С» и не аффилирован с ней.