Как просуммировать и сгруппировать время в запросе 1С

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

В платформе 1С отсутствует отдельный тип данных для хранения только времени. Для работы с временными значениями используется тип Дата, содержащий как дату, так и время (например, 0001-01-01 01:30:00). Из-за этого напрямую применить агрегатную функцию СУММА() к полю с временем в языке запросов нельзя — платформа выдаст ошибку несовместимости типов.

Рассмотрим, как правильно решить задачу группировки и суммирования времени по пользователям или объектам средствами языка запросов 1С и последующей обработки результатов.

Способ 1. Перевод времени в секунды через функции работы с датой

Для выполнения арифметического суммирования необходимо перевести составные части времени (часы, минуты и секунды) в единую числовую величину — общее количество секунд от начала суток. После этого к полученному числу можно применить стандартную группировку и функцию СУММА().

Разберем пример запроса, где время раскладывается на составляющие с помощью функций ЧАС(), МИНУТА() и СЕКУНДА():


ВЫБРАТЬ
	ТаблицаДанных.ФИО КАК ФИО,
	СУММА(ЧАС(ТаблицаДанных.ВремяСвободен) * 3600 
		+ МИНУТА(ТаблицаДанных.ВремяСвободен) * 60 
		+ СЕКУНДА(ТаблицаДанных.ВремяСвободен)) КАК ВсегоСекунд
ИЗ
	РегистрСведений.ЗанятостьСотрудников КАК ТаблицаДанных
СГРУППИРОВАТЬ ПО
	ТаблицаДанных.ФИО

Альтернативным и более компактным вариантом перевода даты/времени в секунды является использование функции РАЗНОСТЬДАТ() от начала пустой даты ДАТАВРЕМЯ(1, 1, 1):


ВЫБРАТЬ
	ТаблицаДанных.ФИО КАК ФИО,
	СУММА(РАЗНОСТЬДАТ(ДАТАВРЕМЯ(1, 1, 1), ТаблицаДанных.ВремяСвободен, СЕКУНДА)) КАК ВсегоСекунд
ИЗ
	РегистрСведений.ЗанятостьСотрудников КАК ТаблицаДанных
СГРУППИРОВАТЬ ПО
	ТаблицаДанных.ФИО

Способ 2. Преобразование суммы секунд обратно в формат времени в запросе

Если суммарное время заведомо не превышает 24 часа (86 400 секунд), результат можно прибавить обратно к пустой дате с помощью функции ДОБАВИТЬКДАТЕ() прямо в запросе:


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

Важное ограничение: если общая сумма секунд превысит 24 часа, произойдет переход через сутки (дата станет 0001-01-02). При выводе такого поля в формате времени отобразится только остаток от текущих суток, а не накопительное время. Чтобы отработало корректное отображение значения свыше 24 часов, требуется программная обработка результатов.

Способ 3. Программное форматирование итогов (более 24 часов)

Если сумма длительности может превышать 24 часа, вычисление итогового значения лучше выполнять на встроенном языке 1С после выполнения запроса:

  1. В запросе получаем только сумму секунд ВсегоСекунд по группировке.
  2. Во встроенном языке производим расчет часов, минут и секунд математическими операциями деления и остатка от деления.

Рассмотрим пример кода для обработки результатов выборки запроса:


Пока Выборка.Следующий() Цикл
	ВсегоСекунд = Выборка.ВсегоСекунд;
	
	КоличествоЧасов = Цел(ВсегоСекунд / 3600);
	ОстатокСекунд = ВсегоСекунд % 3600;
	КоличествоМинут = Цел(ОстатокСекунд / 60);
	КоличествоСекунд = ОстатокСекунд % 60;
	
	ПредставлениеВремени = СтрШаблон("%1:%2:%3",
		Формат(КоличествоЧасов, "ЧЦ=3; ЧН=00"),
		Формат(КоличествоМинут, "ЧЦ=2; ЧДЦ=0; ЧН=00"),
		Формат(КоличествоСекунд, "ЧЦ=2; ЧДЦ=0; ЧН=00"));
КонецЦикла;

Рекомендации по проектированию структуры данных

Если реквизит или поле регистра предназначены исключительно для учета отработанного времени, задержек или интервалов, оптимальным решением является хранение этого значения в виде числа (например, количество секунд или минут с типом Число(10, 0)). Это избавляет от необходимости вызывать функции РАЗНОСТЬДАТ() или ЧАС() в запросах и позволяет использовать прямую функцию СУММА() без дополнительных преобразований.

← На главную