我想把这一年分成13个时期,每个时间为4周
一年52周/ 4 = 13周期
我希望每个时期都在星期六开始,并在星期五结束。
它应该如下图所示
显然我可以手动执行此操作,但日期会每年更改,我正在寻找一种使用SQL自动执行此操作的方法,而不是为每个即将到来的年份手动执行此操作
有没有办法自动生成这种年度分割?
答案 0 :(得分:1)
在this previous answer中,我展示了创建数字/日期表的方法。这样的桌子在很多地方非常漂亮。
使用这种方法你可以尝试这样的事情:
CREATE TABLE dbo.RunningNumbers(Number INT NOT NULL,CalendarDate DATE NOT NULL, CalendarYear INT NOT NULL,CalendarMonth INT NOT NULL,CalendarDay INT NOT NULL, CalendarWeek INT NOT NULL, CalendarYearDay INT NOT NULL, CalendarWeekDay INT NOT NULL);
DECLARE @CountEntries INT = 100000;
DECLARE @StartNumber INT = 0;
WITH E1(N) AS(SELECT 1 FROM(VALUES (1),(1),(1),(1),(1),(1),(1),(1),(1),(1))t(N)), --10 ^ 1
E2(N) AS(SELECT 1 FROM E1 a CROSS JOIN E1 b), -- 10 ^ 2 = 100 rows
E4(N) AS(SELECT 1 FROM E2 a CROSS JOIN E2 b), -- 10 ^ 4 = 10,000 rows
E8(N) AS(SELECT 1 FROM E4 a CROSS JOIN E4 b), -- 10 ^ 8 = 10,000,000 rows
CteTally AS
(
SELECT TOP(ISNULL(@CountEntries,1000000)) ROW_NUMBER() OVER(ORDER BY(SELECT NULL)) -1 + ISNULL(@StartNumber,0) As Nmbr
FROM E8
)
INSERT INTO dbo.RunningNumbers
SELECT CteTally.Nmbr,CalendarDate.d,CalendarExt.*
FROM CteTally
CROSS APPLY
(
SELECT DATEADD(DAY,CteTally.Nmbr,{ts'1900-01-01 00:00:00'})
) AS CalendarDate(d)
CROSS APPLY
(
SELECT YEAR(CalendarDate.d) AS CalendarYear
,MONTH(CalendarDate.d) AS CalendarMonth
,DAY(CalendarDate.d) AS CalendarDay
,DATEPART(WEEK,CalendarDate.d) AS CalendarWeek
,DATEPART(DAYOFYEAR,CalendarDate.d) AS CalendarYearDay
,DATEPART(WEEKDAY,CalendarDate.d) AS CalendarWeekDay
) AS CalendarExt;
GO
NTILE
- SQL Server 2008+将创建(几乎)偶数块。这是实际查询
SELECT *,NTILE(13) OVER(ORDER BY CalendarDate) AS Periode
FROM RunningNumbers
WHERE CalendarWeekDay=6
AND CalendarDate>={d'2017-01-01'} AND CalendarDate <= {d'2017-12-31'};
GO
--Carefull with existing data!
--DROP TABLE dbo.RunningNumbers;
NTILE
的链接,尤其是备注 -section。我认为这适合这种情况。您可以考虑使用Prdp的方法ROW_NUMBER()
与INT division
同步。但是 - 大优势! - NTILE
会允许PARTITION BY CalendarYear
。
...您可以将期间的数字设置为固定值。这将使未来的查询变得非常简单,并允许在特殊情况下进行手动校正(第53周......)
答案 1 :(得分:1)
这是使用Calendar
表
DECLARE @start DATE = '2017-04-01',
@end_date DATE = '2017-12-31'
SET DATEFIRST 7;
WITH Calendar
AS (SELECT 1 AS id,
@start AS start_date,
Dateadd(dd, 6, @start) AS end_date
UNION ALL
SELECT id + 1,
Dateadd(week, 1, start_date),
Dateadd(week, 1, end_date)
FROM Calendar
WHERE end_date < @end_date)
SELECT id,
( Row_number()OVER(ORDER BY id) - 1 ) / 4 + 1 AS Period,
start_date,
end_date
FROM Calendar
OPTION (maxrecursion 0)
我使用Recursive CTE
生成了日期,但最好创建一个物理日历表,在这样的查询中使用它
答案 2 :(得分:0)
首先,一年中你将永远不会得到52周,大多数日历标准都有重叠周。你偶尔会得到53周。
您可以告诉SQL使用星期六作为datefirst
的一周的第一天,然后在getdate()
的今天运行datepart会告诉您一年中的一周:
SET datefirst 6 -- 6 is Saturday
SELECT datepart(ww,getdate()) as currentWeek
然后您可以使用CEILING
命令将此除以4以获得4周的分割:
SET datefirst 6
SELECT DATEPART(ww,getdate()) as currentWeek,
CEILING(DATEPART(ww,getdate())/4) as four_week_split