您首先需要找到该月第一天的一周开始日期,然后是包含该月最后一天的一周结束日期:
例如
SELECT WeekStart = DATEADD(DAY, -(DATEPART(WEEKDAY, '20200401')-1), '20200401'),
WeekEnd = DATEADD(DAY, 7-(DATEPART(WEEKDAY, '20200430')), '20200430');
给予:
WeekStart WeekEnd
------------------------------
2020-03-29 2020-05-02
您不想硬编码每月的第一天和最后一天,但这些都是从日期中获得的相当微不足道的东西:
DECLARE @Date DATE = '20200415';
SELECT MonthStart = DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0),
MonthEnd = EOMONTH(@Date);
返回
MonthStart MonthEnd
------------------------------
2020-04-01 2020-04-30
然后,您可以将其替换为第一个查询周开始:
DECLARE @Date DATE = '20200401';
SELECT WeekStart = DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0))-1), DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0)),
WeekEnd = DATEADD(DAY, 7-(DATEPART(WEEKDAY, EOMONTH(@Date))), EOMONTH(@Date));
这给出了与第一个带有硬编码日期的查询相同的输出。不过这很笨拙,所以我将把它分成更进一步的步骤:
DECLARE @Date DATE = '20200401';
-- SET DATE TO THE FIRST OF THE MONTH IN CASE IT IS NOT ALREADY
SET @Date = DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0);
SELECT WeekStart = DATEADD(DAY, -(DATEPART(WEEKDAY, @Date)-1), @Date),
Weekend = DATEADD(DAY, 7-(DATEPART(WEEKDAY, EOMONTH(@Date))), EOMONTH(@Date));
同样,这给出了相同的输出(2020-03-29 和 2020-05-02)。
下一步是填写工作日之间的所有日期。如果你有calendar table,这很简单
DECLARE @Date DATE = '20200415';
-- SET DATE TO THE FIRST OF THE MONTH IN CASE IT IS NOT ALREADY
SET @Date = DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0);
DECLARE @Start DATE = DATEADD(DAY, -(DATEPART(WEEKDAY, @Date)-1), @Date),
@End DATE = DATEADD(DAY, 7-(DATEPART(WEEKDAY, EOMONTH(@Date))), EOMONTH(@Date));
SELECT [Date], DayName = DATENAME(WEEKDAY, [Date])
FROM Calendar
WHERE Date >= @Start
AND Date <= @End
AND IsWeekday = 1
ORDER BY [Date];
如果您没有日历表,那么我建议您创建一个,但如果您无法创建一个,您仍然可以通过generating a set series numbers 即时生成它,并将这些数字添加到您的开始日期:
DECLARE @Date DATE = '20200415';
-- SET DATE TO THE FIRST OF THE MONTH IN CASE IT IS NOT ALREADY
SET @Date = DATEADD(MONTH, DATEDIFF(MONTH, 0, @Date), 0);
DECLARE @Start DATE = DATEADD(DAY, -(DATEPART(WEEKDAY, @Date)-1), @Date),
@End DATE = DATEADD(DAY, 7-(DATEPART(WEEKDAY, EOMONTH(@Date))), EOMONTH(@Date));
-- GET NUMBERS FROM 0 - 50
WITH Dates (Date) AS
( SELECT TOP (DATEDIFF(DAY, @Start, @End))
DATEADD(DAY, ROW_NUMBER() OVER(ORDER BY n1.n) - 1, @Start)
FROM (VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1)) n1 (n)
CROSS JOIN (VALUES (1),(1),(1),(1),(1)) n2 (n)
)
SELECT [Date], DayName = DATENAME(WEEKDAY, [Date])
FROM Dates
WHERE ((DATEPART(WEEKDAY, [Date]) + @@DATEFIRST) % 7) NOT IN (0, 1);