То, как вы перебираете строки в SQL, заключается в том, что вы этого не делаете. SQL - это язык на основе множеств, который требует совершенно другого мышления, чем другие процедурные языки. Если вы собираетесь работать с SQL, вам действительно необходимо изменить этот подход, думая, что он будет успешным.
Вот как бы я справился с этим:
SELECT
CONVERT(VARCHAR(10), StartTime, 121) AS [date],
name,
SUM(work)
FROM
My_Table
WHERE
StartTime >= @start_date AND
StartTime < DATEADD(dy, 1, @finish_date)
GROUP BY
CONVERT(VARCHAR(10), StartTime, 121),
name
Кроме того, ваш дизайн таблицы выглядит так, как будто он нарушает нормальные стандарты проектирования баз данных. Ваш столбец "работа" на самом деле просто расчет между StartTime и FinishTime. Это делает дублирование одних и тех же данных, что может вызвать всевозможные проблемы. Например, что вы делаете, когда ваши StartTime и FinishTime разнесены на 4 часа, а «Работа» означает 5 часов?
Чтобы включить даты без связанной работы, вам нужно либо обработать их во внешнем интерфейсе, либо вам понадобится таблица «Календарь». В нем будут все даты, и вы сделаете ЛЕВОЕ СОЕДИНЕНИЕ к этому со своей таблицей. Например:
SELECT
CONVERT(VARCHAR(10), C.StartTime, 121) AS [date],
MT.name,
SUM(MT.work)
FROM
Calendar C
LEFT JOIN My_Table MT ON
MT.StartDate BETWEEN C.StartTime and C.FinishTime
WHERE
C.StartTime >= @start_date AND
C.StartTime < DATEADD(dy, 1, @finish_date)
GROUP BY
CONVERT(VARCHAR(10), C.StartTime, 121),
MT.name
Таблица календаря также позволяет добавлять к датам дополнительную информацию, такую как флаг для праздничных дней, «сверхурочные» дни (возможно, работа считается как полтора раза по воскресеньям) и т. Д.
ПРИМЕЧАНИЕ : Решение Чарльза Бретаны, вероятно, немного чище, поскольку он сохраняет типы данных в виде даты-времени, а не превращает их в строки. Я собираюсь оставить это здесь для некоторых других комментариев.