从周数获取周开始日期和周结束日期
Posted
技术标签:
【中文标题】从周数获取周开始日期和周结束日期【英文标题】:Get the week start date and week end date from week number 【发布时间】:2010-11-19 00:32:30 【问题描述】:我有一个查询数据库中成员的婚礼日期。
SELECT
SUM(NumberOfBrides) AS [Wedding Count]
, DATEPART( wk, WeddingDate) AS [Week Number]
, DATEPART( year, WeddingDate) AS [Year]
FROM MemberWeddingDates
GROUP BY DATEPART(year, WeddingDate), DATEPART(wk, WeddingDate)
ORDER BY SUM(NumberOfBrides) DESC
如何计算结果集中显示每周的开始和结束时间?
SELECT
SUM(NumberOfBrides) AS [Wedding Count]
, DATEPART(wk, WeddingDate) AS [Week Number]
, DATEPART(year, WeddingDate) AS [Year]
, ??? AS WeekStart
, ??? AS WeekEnd
FROM MemberWeddingDates
GROUP BY DATEPART(year, WeddingDate), DATEPART(wk, WeddingDate)
ORDER BY SUM(NumberOfBrides) DESC
【问题讨论】:
【参考方案1】:您可以找到星期几并添加日期以获取开始和结束日期..
DATEADD(dd, -(DATEPART(dw, WeddingDate)-1), WeddingDate) [WeekStart]
DATEADD(dd, 7-(DATEPART(dw, WeddingDate)), WeddingDate) [WeekEnd]
不过,您可能还想看看从日期中删除时间。
【讨论】:
请记住,将DATEFIRST
设置为 7 以外的任何值都会破坏这一点。
它不会“破坏”它,它会使用 datefirst 将 WeekStart = 设置为 DateFirst 所说的一周的第一天。您的版本将始终将星期一和星期日作为一周的开始和结束,而不是服务器设置为一周的开始和结束
嗯...这是一个有效的观点,+1。 :) 我会删除我的,然后(虽然是脚上的一枪,但它的目标非常好。g)。
好吧,那我再次取消删除它。无论如何,我不确定谁会在他们的头脑中假设除星期一以外的任何事情都是一周的开始。 无论如何 开始星期天是没有意义的。 :-)
'set datefirst 1' 为星期一 (msdn.microsoft.com/en-ie/library/ms181598.aspx)【参考方案2】:
这是一个DATEFIRST
不可知的解决方案:
SET DATEFIRST 4 /* or use any other weird value to test it */
DECLARE @d DATETIME
SET @d = GETDATE()
SELECT
@d ThatDate,
DATEADD(dd, 0 - (@@DATEFIRST + 5 + DATEPART(dw, @d)) % 7, @d) Monday,
DATEADD(dd, 6 - (@@DATEFIRST + 5 + DATEPART(dw, @d)) % 7, @d) Sunday
【讨论】:
这很好,但星期一不适合我。我必须添加“0 -”才能获得星期一。我的星期一代码现在是:DATEADD(dd, 0 - (@@DATEFIRST + 5 + DATEPART(dw, @d)) % 7, @d) 赞成答案和沃伦斯评论。 Sql Server 版本 11.0.5058.0 至少在没有 Warrens 修改的情况下给出了错误的星期一日期。而是给我星期五。【参考方案3】:以下查询将提供当前一周开始和结束之间的数据 从周日到周六开始
SELECT DOB FROM PROFILE_INFO WHERE DAY(DOB) BETWEEN
DAY( CURRENT_DATE() - (SELECT DAYOFWEEK(CURRENT_DATE())-1))
AND
DAY((CURRENT_DATE()+(7 - (SELECT DAYOFWEEK(CURRENT_DATE())) ) ))
AND
MONTH(DOB)=MONTH(CURRENT_DATE())
【讨论】:
【参考方案4】:我刚刚遇到了一个类似的案例,但是这里的解决方案似乎对我没有帮助。 所以我试着自己弄清楚。我只计算周开始日期,周结束日期应该是类似的逻辑。
Select
Sum(NumberOfBrides) As [Wedding Count],
DATEPART( wk, WeddingDate) as [Week Number],
DATEPART( year, WeddingDate) as [Year],
DATEADD(DAY, 1 - DATEPART(WEEKDAY, dateadd(wk, DATEPART( wk, WeddingDate)-1, DATEADD(yy,DATEPART( year, WeddingDate)-1900,0))), dateadd(wk, DATEPART( wk, WeddingDate)-1, DATEADD(yy,DATEPART( year, WeddingDate)-1900,0))) as [Week Start]
FROM MemberWeddingDates
Group By DATEPART( year, WeddingDate), DATEPART( wk, WeddingDate)
Order By Sum(NumberOfBrides) Desc
【讨论】:
【参考方案5】:对于访问查询,您可以使用以下格式作为字段
"FirstDayofWeek:IIf(IsDate([ForwardedForActionDate]),CDate(Format([ForwardedForActionDate],"dd/mm/yyyy"))-(Weekday([ForwardedForActionDate])-1))"
允许直接计算..
【讨论】:
【参考方案6】:你也可以使用这个:
SELECT DATEADD(day, DATEDIFF(day, 0, WeddingDate) /7*7, 0) AS weekstart,
DATEADD(day, DATEDIFF(day, 6, WeddingDate-1) /7*7 + 7, 6) AS WeekEnd
【讨论】:
我最喜欢这个版本,最适合在没有时间的情况下获得不可知的周一到周日日期,您只需每行输入一次日期。【参考方案7】:不确定这有多大用处,但我最终在这里寻找有关 Netezza SQL 的解决方案,但在堆栈溢出时找不到解决方案。
对于 IBM netezza,您可以使用以下内容(对于 week start mon,week end sun),例如:
选择 next_day (WeddingDate, 'SUN') -6 作为 WeekStart,
next_day (WeddingDate, 'SUN') 作为周末
【讨论】:
【参考方案8】:这是另一个版本。如果您的方案要求星期六是一周的第一天,星期五是一周的最后一天,下面的代码将处理这个问题:
DECLARE @myDate DATE = GETDATE()
SELECT @myDate,
DATENAME(WEEKDAY,@myDate),
DATEADD(DD,-(CHOOSE(DATEPART(dw, @myDate), 1,2,3,4,5,6,0)),@myDate) AS WeekStartDate,
DATEADD(DD,7-CHOOSE(DATEPART(dw, @myDate), 2,3,4,5,6,7,1),@myDate) AS WeekEndDate
【讨论】:
【参考方案9】:扩展 @Tomalak's 答案。该公式适用于星期日和星期一以外的日子,但您需要对 5 的位置使用不同的值。达到您需要的价值的一种方法是
Value Needed = 7 - (Value From Date First Documentation for Desired Day Of Week) - 1
这里是文档的链接:https://msdn.microsoft.com/en-us/library/ms181598.aspx
这里有一张表格,可以为您安排。
| DATEFIRST VALUE | Formula Value | 7 - DATEFIRSTVALUE - 1
Monday | 1 | 5 | 7 - 1- 1 = 5
Tuesday | 2 | 4 | 7 - 2 - 1 = 4
Wednesday | 3 | 3 | 7 - 3 - 1 = 3
Thursday | 4 | 2 | 7 - 4 - 1 = 2
Friday | 5 | 1 | 7 - 5 - 1 = 1
Saturday | 6 | 0 | 7 - 6 - 1 = 0
Sunday | 7 | -1 | 7 - 7 - 1 = -1
但您不必只记住该表和公式,实际上您也可以使用稍微不同的表,主要需要使用一个值,使余数成为正确的天数。
这是一个工作示例:
DECLARE @MondayDateFirstValue INT = 1
DECLARE @FridayDateFirstValue INT = 5
DECLARE @TestDate DATE = GETDATE()
SET @MondayDateFirstValue = 7 - @MondayDateFirstValue - 1
SET @FridayDateFirstValue = 7 - @FridayDateFirstValue - 1
SET DATEFIRST 6 -- notice this is saturday
SELECT
DATEADD(DAY, 0 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as MondayStartOfWeek
,DATEADD(DAY, 6 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as MondayEndOfWeek
,DATEADD(DAY, 0 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as FridayStartOfWeek
,DATEADD(DAY, 6 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as FridayEndOfWeek
SET DATEFIRST 2 --notice this is tuesday
SELECT
DATEADD(DAY, 0 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as MondayStartOfWeek
,DATEADD(DAY, 6 - (@@DATEFIRST + @MondayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as MondayEndOfWeek
,DATEADD(DAY, 0 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as FridayStartOfWeek
,DATEADD(DAY, 6 - (@@DATEFIRST + @FridayDateFirstValue + DATEPART(dw,@TestDate)) % 7, @TestDate) as FridayEndOfWeek
此方法与 DATEFIRST
设置无关,这是我在构建包含多周方法的日期维度时所需要的。
【讨论】:
【参考方案10】:除了一年中的第一周和最后一周之外,投票最多的答案效果很好。例如,如果WeddingDate 的值为'2016-01-01',则结果将是2015-12-27 和2016-01-02,但右答案是 2016-01-01 和 2016-01-02。
试试这个:
Select
Sum(NumberOfBrides) As [Wedding Count],
DATEPART( wk, WeddingDate) as [Week Number],
DATEPART( year, WeddingDate) as [Year],
MAX(CASE WHEN DATEPART(WEEK, WeddingDate) = 1 THEN CAST(DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0) AS date) ELSE DATEADD(DAY, 7 * DATEPART(WEEK, WeddingDate), DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0))) END) as WeekStart,
MAX(CASE WHEN DATEPART(WEEK, WeddingDate) = DATEPART(WEEK, DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate) + 1, 0))) THEN DATEADD(DAY, -1, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate) + 1, 0)) ELSE DATEADD(DAY, 7 * DATEPART(WEEK, WeddingDate) + 6, DATEADD(DAY, -(DATEPART(WEEKDAY, DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0)) + 6), DATEADD(YEAR, DATEDIFF(YEAR, 0, WeddingDate), 0))) END) as WeekEnd
FROM MemberWeddingDates
Group By DATEPART( year, WeddingDate), DATEPART( wk, WeddingDate)
Order By Sum(NumberOfBrides) Desc;
结果如下:
它适用于所有周,第一周或其他周。
【讨论】:
【参考方案11】:让我们把问题分解成两部分:
1) 确定星期几
DATEPART(dw, ...)
返回一个数字,1...7,相对于 DATEFIRST
设置 (docs)。下表总结了可能的值:
@@DATEFIRST
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
| | 1 | 2 | 3 | 4 | 5 | 6 | 7 | DOW |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
| DATEPART(dw, /*Mon*/ '20010101') | 1 | 7 | 6 | 5 | 4 | 3 | 2 | 1 |
| DATEPART(dw, /*Tue*/ '20010102') | 2 | 1 | 7 | 6 | 5 | 4 | 3 | 2 |
| DATEPART(dw, /*Wed*/ '20010103') | 3 | 2 | 1 | 7 | 6 | 5 | 4 | 3 |
| DATEPART(dw, /*Thu*/ '20010104') | 4 | 3 | 2 | 1 | 7 | 6 | 5 | 4 |
| DATEPART(dw, /*Fri*/ '20010105') | 5 | 4 | 3 | 2 | 1 | 7 | 6 | 5 |
| DATEPART(dw, /*Sat*/ '20010106') | 6 | 5 | 4 | 3 | 2 | 1 | 7 | 6 |
| DATEPART(dw, /*Sun*/ '20010107') | 7 | 6 | 5 | 4 | 3 | 2 | 1 | 7 |
+------------------------------------+-----+-----+-----+-----+-----+-----+-----+-----+
最后一列包含周一至周日的理想周值*。通过查看图表,我们得出以下等式:
(@@DATEFIRST + DATEPART(dw, SomeDate) - 1 - 1) % 7 + 1
2) 计算给定日期的星期一和星期日
这要归功于星期几的值。这是一个例子:
WITH TestData(SomeDate) AS (
SELECT CAST('20001225' AS DATETIME) UNION ALL
SELECT CAST('20001226' AS DATETIME) UNION ALL
SELECT CAST('20001227' AS DATETIME) UNION ALL
SELECT CAST('20001228' AS DATETIME) UNION ALL
SELECT CAST('20001229' AS DATETIME) UNION ALL
SELECT CAST('20001230' AS DATETIME) UNION ALL
SELECT CAST('20001231' AS DATETIME) UNION ALL
SELECT CAST('20010101' AS DATETIME) UNION ALL
SELECT CAST('20010102' AS DATETIME) UNION ALL
SELECT CAST('20010103' AS DATETIME) UNION ALL
SELECT CAST('20010104' AS DATETIME) UNION ALL
SELECT CAST('20010105' AS DATETIME) UNION ALL
SELECT CAST('20010106' AS DATETIME) UNION ALL
SELECT CAST('20010107' AS DATETIME) UNION ALL
SELECT CAST('20010108' AS DATETIME) UNION ALL
SELECT CAST('20010109' AS DATETIME) UNION ALL
SELECT CAST('20010110' AS DATETIME) UNION ALL
SELECT CAST('20010111' AS DATETIME) UNION ALL
SELECT CAST('20010112' AS DATETIME) UNION ALL
SELECT CAST('20010113' AS DATETIME) UNION ALL
SELECT CAST('20010114' AS DATETIME)
), TestDataPlusDOW AS (
SELECT SomeDate, (@@DATEFIRST + DATEPART(dw, SomeDate) - 1 - 1) % 7 + 1 AS DOW
FROM TestData
)
SELECT
FORMAT(SomeDate, 'ddd yyyy-MM-dd') AS SomeDate,
FORMAT(DATEADD(dd, -DOW + 1, SomeDate), 'ddd yyyy-MM-dd') AS [Monday],
FORMAT(DATEADD(dd, -DOW + 1 + 6, SomeDate), 'ddd yyyy-MM-dd') AS [Sunday]
FROM TestDataPlusDOW
输出:
+------------------+------------------+------------------+
| SomeDate | Monday | Sunday |
+------------------+------------------+------------------+
| Mon 2000-12-25 | Mon 2000-12-25 | Sun 2000-12-31 |
| Tue 2000-12-26 | Mon 2000-12-25 | Sun 2000-12-31 |
| Wed 2000-12-27 | Mon 2000-12-25 | Sun 2000-12-31 |
| Thu 2000-12-28 | Mon 2000-12-25 | Sun 2000-12-31 |
| Fri 2000-12-29 | Mon 2000-12-25 | Sun 2000-12-31 |
| Sat 2000-12-30 | Mon 2000-12-25 | Sun 2000-12-31 |
| Sun 2000-12-31 | Mon 2000-12-25 | Sun 2000-12-31 |
| Mon 2001-01-01 | Mon 2001-01-01 | Sun 2001-01-07 |
| Tue 2001-01-02 | Mon 2001-01-01 | Sun 2001-01-07 |
| Wed 2001-01-03 | Mon 2001-01-01 | Sun 2001-01-07 |
| Thu 2001-01-04 | Mon 2001-01-01 | Sun 2001-01-07 |
| Fri 2001-01-05 | Mon 2001-01-01 | Sun 2001-01-07 |
| Sat 2001-01-06 | Mon 2001-01-01 | Sun 2001-01-07 |
| Sun 2001-01-07 | Mon 2001-01-01 | Sun 2001-01-07 |
| Mon 2001-01-08 | Mon 2001-01-08 | Sun 2001-01-14 |
| Tue 2001-01-09 | Mon 2001-01-08 | Sun 2001-01-14 |
| Wed 2001-01-10 | Mon 2001-01-08 | Sun 2001-01-14 |
| Thu 2001-01-11 | Mon 2001-01-08 | Sun 2001-01-14 |
| Fri 2001-01-12 | Mon 2001-01-08 | Sun 2001-01-14 |
| Sat 2001-01-13 | Mon 2001-01-08 | Sun 2001-01-14 |
| Sun 2001-01-14 | Mon 2001-01-08 | Sun 2001-01-14 |
+------------------+------------------+------------------+
* 对于周日到周六这周,您需要稍微调整一下等式,例如在某处加 1。
【讨论】:
【参考方案12】:这不是来自我,但无论如何它都完成了工作:
SELECT DATEADD(wk, -1, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day previous week
SELECT DATEADD(wk, 0, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day current week
SELECT DATEADD(wk, 1, DATEADD(DAY, 1-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --first day next week
SELECT DATEADD(wk, 0, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day previous week
SELECT DATEADD(wk, 1, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day current week
SELECT DATEADD(wk, 2, DATEADD(DAY, 0-DATEPART(WEEKDAY, GETDATE()), DATEDIFF(dd, 0, GETDATE()))) --last day next week
我找到了here。
【讨论】:
【参考方案13】:Power BI Dax 公式的周开始和结束日期
WeekStartDate = [DateColumn] - (WEEKDAY([DateColumn])-1)
WeekEndDate = [DateColumn] + (7-WEEKDAY([DateColumn]))
【讨论】:
【参考方案14】:这是我的解决方案
设置日期优先 1; /* 更改为使用不同的 datefirst */ 声明@date DATETIME SET @date = CAST('2/6/2019' 作为日期) SELECT DATEADD(dd,0 - (DATEPART(dw, @date) - 1) ,@date) [dateFrom], DATEADD(dd,6 - (DATEPART(dw, @date) - 1) ,@date) [dateTo]【讨论】:
【参考方案15】:按自定义日期获取开始日期和结束日期
DECLARE @Date NVARCHAR(50)='05/19/2019'
SELECT
DATEADD(DAY,CASE WHEN DATEPART(WEEKDAY, @Date)=1 THEN -6 ELSE 2 - DATEPART(WEEKDAY, @Date) END, CAST(@Date AS DATE)) [Week_Start_Date]
,DATEADD(DAY,CASE WHEN DATEPART(WEEKDAY, @Date)=1 THEN 0 ELSE 8 - DATEPART(WEEKDAY, @Date) END, CAST(@Date AS DATE)) [Week_End_Date]
【讨论】:
虽然这段代码可以解决问题,但including an explanation 确实有助于提高帖子的质量。【参考方案16】:我还有其他方法,选择日期开始和周结束日期当前:
DATEADD(d, -(DATEPART(dw, GETDATE()-2)), GETDATE()) 是日期时间开始
和
DATEADD(day,7-(DATEPART(dw,GETDATE()-1)),GETDATE()) 是日期时间结束
【讨论】:
【参考方案17】:另一种方法:
declare @week_number int = 6280 -- 2020-05-07
declare @start_weekday int = 0 -- Monday
declare @end_weekday int = 6 -- next Sunday
select
dateadd(week, @week_number, @start_weekday),
dateadd(week, @week_number, @end_weekday)
解释:
@week_number 是自初始日历日期“1900-01-01”以来的周数。可以这样计算:select datediff(week, 0, @wedding_date) as week_number
@start_weekday 表示一周的第一天:0 表示周一,-1 表示周日
@end_weekday 表示上周的最后一天:6 表示下周日,5 表示周六
dateadd(week, @week_number, @end_weekday)
:将给定的周数和给定的天数添加到初始日历日期'1900-01-01'
【讨论】:
【参考方案18】:如果星期天被认为是一周的开始日,那么这里是代码
Declare @currentdate date = '18 Jun 2020'
select DATEADD(D, -(DATEPART(WEEKDAY, @currentdate) - 1), @currentdate)
select DATEADD(D, (7 - DATEPART(WEEKDAY, @currentdate)), @currentdate)
【讨论】:
以上是关于从周数获取周开始日期和周结束日期的主要内容,如果未能解决你的问题,请参考以下文章