При анализе эффективности работы торговой точки часто возникает задача распределения нагрузки по часам. Например, необходимо понять, в какие периоды времени (с 8:00 до 9:00, с 9:00 до 10:00 и так далее) пробивается наибольшее количество чеков. В этой статье мы разберем, как реализовать такую задачу с помощью механизмов платформы 1С:Предприятие 8, используя язык запросов и программную обработку результатов.
Представим ситуацию: у нас есть внешняя база данных (через ВнешнийИсточникДанных) или внутренняя таблица с документами, где хранится время закрытия чека в формате Дата (например, 01.01.2020 12:34:56). Нам нужно получить таблицу, в которой будет две колонки: Период (текстовое или временное представление часа) и Количество (число закрытых чеков за этот час).
Рассмотрим исходный запрос, который выбирает просто список всех времен закрытия:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ
| sms_Cheque.CloseTime КАК Время
|ИЗ
| ВнешнийИсточникДанных.SIS.Таблица.sms_Cheque КАК sms_Cheque
|ГДЕ
| sms_Cheque.CloseTime МЕЖДУ &ДатаНач И &ДатаКон";
Этот запрос выдаст нам сырые данные, которые неудобно анализировать. Чтобы сгруппировать их по часам, нам потребуется функция НАЧАЛОПЕРИОДА.
Самый эффективный способ решить задачу — переложить расчеты на сторону СУБД. Для этого мы используем функцию НАЧАЛОПЕРИОДА(Дата, ЧАС). Она "отсекает" минуты и секунды, превращая любое время внутри часа в начало этого часа. Например, 12:34:56 станет 12:00:00.
Проанализируем правильную структуру запроса:
ВЫБРАТЬ
НАЧАЛОПЕРИОДА(sms_Cheque.CloseTime, ЧАС) КАК ЧасЗакрытия,
КОЛИЧЕСТВО(*) КАК КоличествоЧеков
ИЗ
ВнешнийИсточникДанных.SIS.Таблица.sms_Cheque КАК sms_Cheque
ГДЕ
sms_Cheque.CloseTime МЕЖДУ &ДатаНач И &ДатаКон
СГРУППИРОВАТЬ ПО
НАЧАЛОПЕРИОДА(sms_Cheque.CloseTime, ЧАС)
УПОРЯДОЧИТЬ ПО
ЧасЗакрытия
Почему это работает:
НАЧАЛОПЕРИОДА с параметром ЧАС позволяет объединить все записи, относящиеся к одному часу, в одну группу.КОЛИЧЕСТВО(*) подсчитывает число записей в каждой сформированной группе.СГРУППИРОВАТЬ ПО обязательна, так как мы используем агрегатные функции вместе с обычными полями.Вышеуказанный запрос имеет одну особенность: если в период с 14:00 до 15:00 не было ни одного чека, эта строка вообще не попадет в результат запроса. Однако для отчета пользователю часто важно видеть все часы (с 8 до 23), даже если там стоят нули.
Рассмотрим, как заполнить недостающие интервалы программно в ТаблицеЗначений. Сначала создадим эталонную таблицу со всеми нужными нам часами:
// Создаем таблицу для результата
ТабРезультат = Новый ТаблицаЗначений;
ТабРезультат.Колонки.Добавить("Период", Новый ОписаниеТипов("Строка"));
ТабРезультат.Колонки.Добавить("Количество", Новый ОписаниеТипов("Число"));
// Заполняем её шаблонами часов с 8 до 23
Для ч = 8 По 23 Цикл
НоваяСтр = ТабРезультат.Добавить();
НоваяСтр.Период = "с " + ч + " до " + (ч + 1);
НоваяСтр.Количество = 0;
КонецЦикла;
// Выполняем запрос
Результат = Запрос.Выполнить().Выбрать();
// Обходим результат запроса и обновляем данные в нашей таблице
Пока Результат.Следующий() Цикл
ТекущийЧас = Час(Результат.ЧасЗакрытия);
Если ТекущийЧас >= 8 И ТекущийЧас <= 23 Тогда
// Находим нужную строку в эталонной таблице
// (Индекс строки будет ТекущийЧас - 8, так как начали с 8)
ТабРезультат[ТекущийЧас - 8].Количество = Результат.КоличествоЧеков;
КонецЕсли;
КонецЦикла;
При работе с ВнешнийИсточникДанных важно помнить, что 1С пытается транслировать функции языка запросов (такие как НАЧАЛОПЕРИОДА) в синтаксис конкретной СУБД (SQL Server, MySQL и др.). В некоторых случаях сложные функции могут не поддерживаться драйвером.
Если НАЧАЛОПЕРИОДА выдает ошибку, проанализируем альтернативный вариант — использование функции ЧАС(Дата):
ВЫБРАТЬ
ЧАС(sms_Cheque.CloseTime) КАК ТолькоЧас,
КОЛИЧЕСТВО(*) КАК КоличествоЧеков
ИЗ
ВнешнийИсточникДанных.SIS.Таблица.sms_Cheque КАК sms_Cheque
ГДЕ
sms_Cheque.CloseTime МЕЖДУ &ДатаНач И &ДатаКон
СГРУППИРОВАТЬ ПО
ЧАС(sms_Cheque.CloseTime)
Функция ЧАС вернет просто число от 0 до 23. Это значение еще проще использовать для поиска нужной строки в ТаблицаЗначений или для формирования красивого текстового представления.
Если задача стоит шире, чем просто вывод в таблицу на форме, лучше использовать Систему компоновки данных (СКД). Выясним, какие преимущества это дает:
ЧасЗакрытия можно включить флаг "Дополнять периоды". Система сама добавит строки с нулевыми значениями для отсутствующих часов без написания кода на языке 1С.Выполним оценку производительности: если в таблице чеков миллионы записей, группировка по вычисляемому полю (функции НАЧАЛОПЕРИОДА или ЧАС) может работать медленно, так как СУБД придется вычислять значение для каждой строки.
Если этот отчет планируется формировать часто, рекомендуется:
CloseTime.Таким образом, мы рассмотрели несколько способов решения задачи: от простого запроса с группировкой до создания гибкого отчета с заполнением пустых интервалов. Выбор конкретного метода зависит от требований к визуализации и объема данных в вашей системе.