Я немного догадываюсь о том, что вы пытаетесь сделать, но вот мое лучшее предположение:
Во-первых, в вашей базе данных должна быть таблица календаря:
CREATE TABLE Calendar (
calendar_date DATETIME NOT NULL,
week_number INT NOT NULL,
CONSTRAINT PK_Calendar PRIMARY KEY CLUSTERED (calendar_date)
)
GO
INSERT INTO Calendar (calendar_date, week_number) VALUES ('1/1/2009', 1)
INSERT INTO Calendar (calendar_date, week_number) VALUES ('2/1/2009', 2)
etc.
Вы можете добавить дополнительные столбцы в таблицу в зависимости от потребностей вашего бизнеса. Например, битовый столбец is_holiday, чтобы отслеживать, закрыт ли ваш офис в этот день. Эта таблица делает множество разных запросов тривиальными.
Теперь к вашей проблеме:
SELECT
CAL.week_number,
COUNT(DISTINCT C.component_id)
FROM
Calendar CAL
LEFT OUTER JOIN Components C ON
C.status_date = CAL.calendar_date AND
C.status IN ('01', '02')
WHERE
CAL.calendar_date BETWEEN @start_date AND @end_date
GROUP BY
CAL.week_number
Я использовал IN для статуса, так как вы используете строки, поэтому "<'03'" не всегда может дать вам то, что вы хотите. «1» меньше, чем «03» в вашем уме? </p>
Кроме того, если на какой-либо из ваших дат имеется компонент времени, проверки на равенство и МЕЖДУ могут потребоваться изменить.
РЕДАКТИРОВАТЬ : Я только что увидел комментарии к другому ответу. Если вы имеете дело только с изменениями статуса, то следующий запрос должен работать, хотя может быть более эффективный метод:
SELECT
CAL.week_number,
COUNT(DISTINCT C.component_id)
FROM
Calendar CAL
LEFT OUTER JOIN Components C ON
C.status_date <= CAL.calendar_date AND
C.status IN ('01', '02')
LEFT OUTER JOIN Components C2 ON
C2.component_id = C.component_id AND
C2.status_date > C.status_date AND
C2.status_date <= CAL.calendar_date
WHERE
CAL.calendar_date BETWEEN @start_date AND @end_date AND
C2.component_id IS NULL
GROUP BY
CAL.week_number
Хотя я не уверен, где продукт подходит ко всему этому.