简体   繁体   English

从周数 SQL 服务器获取开始和结束日期

[英]Get Start and End Date from Week Number SQL Server

We have WeekNo and Year entered into a table in following format:我们将WeekNoYear按以下格式输入到表格中:

YYYY-ww     (2021-48)

I want start date and end date from given week no with year as above format.我想从给定的星期开始日期和结束日期,没有年份,格式如上。

How to get it from SQL query or procedure?如何从 SQL 查询或程序中获取它?

Thanks,谢谢,

How about this?这个怎么样?

declare @dateText varchar(7);
declare @week int;
declare @year int;

set datefirst 1;              -- Set first day of week to Monday
set @dateText = '2021-48';
set @year = SUBSTRING(@dateText, 1, 4)
set @week = SUBSTRING(@dateText, 6, 2)

select DATEADD(week, @week, DATEADD(year, @year-1900, 0)) - 4 -
     DATEPART(dw, DATEADD(week, @week, DATEADD(year, @year-1900, 0)) - 4) + 1

Output
-----------------
2021-11-29 00:00:00.000

Alternatively you could create a function:或者,您可以创建一个 function:

CREATE FUNCTION dbo.GetStartOfWeek(@dateText varchar(7))
RETURNS Datetime
BEGIN
    
declare @week int;
declare @year int;
select @year = SUBSTRING(@dateText, 1, 4), @week = SUBSTRING(@dateText, 6, 2)

 RETURN DATEADD(week, @week, DATEADD(year, @year-1900, 0)) - 4 -
        DATEPART(dw, DATEADD(week, @week, DATEADD(year, @year-1900, 0)) - 4) + 1
END;

Which you can use in a SQL query or stored procedure:您可以在 SQL 查询或存储过程中使用它:

select dbo.GetStartOfWeek('2021-48')

Here's a test snippet to calculate the start & end day of a Year-Week in a query.这是一个测试片段,用于计算查询中年周的开始和结束日期。 Without using a User-Defined-Function.不使用用户定义的函数。

SET datefirst 1;
DECLARE @Test TABLE ([YEAR-WW] char(7)); 
INSERT INTO @Test VALUES 
('2021-01'), ('2021-02'), 
('2021-48'), 
('2021-53'), 
('2022-01'), ('2022-02');

SELECT 
  [YEAR-WW]
, [StartOfWeek] = CAST(DATEADD(day, 1-DATEPART(weekday, DATEADD(week, ABS(RIGHT([YEAR-WW],2))-2, LEFT([YEAR-WW],5)+'01-07')), DATEADD(week, ABS(RIGHT([YEAR-WW],2))-2, LEFT([YEAR-WW],5)+'01-07')) AS DATE)
, [EndOfWeek]   = CAST(DATEADD(day, 6, DATEADD(day, 1-DATEPART(weekday, DATEADD(week, ABS(RIGHT([YEAR-WW],2))-2, LEFT([YEAR-WW],5)+'01-07')), DATEADD(week, ABS(RIGHT([YEAR-WW],2))-2, LEFT([YEAR-WW],5)+'01-07'))) AS DATE)
FROM @Test
ORDER BY 1;
 YEAR-WW |年-WW | StartOfWeek |周初 | EndOfWeek:------ |:---------- |:--------- 2021-01 | EndOfWeek:----- |:---------- |:--------- 2021-01 | 2020-12-28 | 2020-12-28 | 2021-01-03 2021-02 | 2021-01-03 2021-02 | 2021-01-04 | 2021-01-04 | 2021-01-10 2021-48 | 2021-01-10 2021-48 | 2021-11-22 | 2021-11-22 | 2021-11-28 2021-53 | 2021-11-28 2021-53 | 2021-12-27 | 2021-12-27 | 2022-01-02 2022-01 | 2022-01-02 2022-01 | 2021-12-27 | 2021-12-27 | 2022-01-02 2022-02 | 2022-01-02 2022-02 | 2022-01-03 | 2022-01-03 | 2022-01-09 2022-01-09

Demo on db<>fiddle here关于db<>fiddle 的演示在这里

(An extra answer, since this method is a bit different.) (一个额外的答案,因为这种方法有点不同。)

This method is about using a tally table with dates and date related stuff.此方法是关于使用带有日期和日期相关内容的计数表。

Then such calendar table can be used to lookup the year and week.然后可以使用这样的日历表来查找年份和星期。

For example例如

create table REF_Calendar ( cal_date date primary key not null, cal_year smallint not null, cal_dayofyear smallint not null, cal_quarter tinyint not null, cal_weekday_abbrev char(3) not null, cal_iso_week tinyint not null, cal_df7_week tinyint not null, cal_df7_weekday tinyint not null, cal_mooncycle tinyint, index idx_Calendar_year_week unique (cal_year, cal_df7_week, cal_df7_weekday) );

Fill the calendar填写日历

SET DATEFIRST 7; -- 7: week starts on sunday declare @startdate date = '2020-01-01'; declare @enddate date = '2023-01-01'; with rcte_calendar as ( select @startdate as cal_date union all select dateadd(day, 1, cal_date) from rcte_calendar where cal_date < @enddate ) insert into ref_calendar (cal_date, cal_year, cal_dayofyear, cal_quarter, cal_weekday_abbrev, cal_iso_week, cal_df7_week, cal_df7_weekday, cal_mooncycle) select cal_date, datepart(year, cal_date) as cal_year, datepart(dayofyear, cal_date) as cal_dayofyear, datepart(quarter, cal_date) as cal_quarter, lower(left(datename(weekday, cal_date), 3)) as cal_weekday_abbrev, datepart(iso_week, cal_date) as cal_iso_week, datepart(week, cal_date) as cal_df7_week, datepart(weekday, cal_date) as cal_df7_weekday, abs(1-abs(round(((14-1.0*CONVERT(int, CONVERT(nvarchar(2), cal_date, 131)))/14), 1, 1)))*100 as cal_mooncycle from rcte_calendar cte where not exists ( select 1 from ref_calendar cal where cal.cal_date = cte.cal_date ) option (maxrecursion 0);
 select top 2 * from ref_calendar order by cal_date desc
cal_date cal_date cal_year cal_year cal_dayofyear cal_dayofyear cal_quarter cal_quarter cal_weekday_abbrev cal_weekday_abbrev cal_iso_week cal_iso_week cal_df7_week cal_df7_week cal_df7_weekday cal_df7_weekday cal_mooncycle cal_mooncycle
2023-01-01 2023-01-01 2023 2023 1 1 1 1 sun太阳 52 52 1 1 1 1 70 70
2022-12-31 2022-12-31 2022 2022 365 365 4 4 sat 52 52 53 53 7 7 60 60

Test测试

DECLARE @Test TABLE (col char(7)); INSERT INTO @Test VALUES ('2021-01'), ('2021-02'), ('2021-48'), ('2022-01'), ('2022-02'); select * from @test t outer apply ( select min(c.cal_date) as startofweek, max(c.cal_date) as endofweek from ref_calendar c cross join (values (try_cast(left(col, 4) as int), abs(try_cast(right(col, 2) as int))) ) as q(yr, ww) where (c.cal_year = yr and c.cal_df7_week = ww) or (ww = 1 and c.cal_year = yr-1 and c.cal_df7_week = 53 and c.cal_dayofyear > 349) or (ww = 53 and c.cal_year = yr+1 and c.cal_df7_week = 1 and c.cal_dayofyear < 7) ) cal
col山口 startofweek周初 endofweek周末
2021-01 2021-01 2020-12-27 2020-12-27 2021-01-02 2021-01-02
2021-02 2021-02 2021-01-03 2021-01-03 2021-01-09 2021-01-09
2021-48 2021-48 2021-11-21 2021-11-21 2021-11-27 2021-11-27
2022-01 2022-01 2021-12-26 2021-12-26 2022-01-01 2022-01-01
2022-02 2022-02 2022-01-02 2022-01-02 2022-01-08 2022-01-08

Demo on db<>fiddle here关于db<>fiddle 的演示在这里

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM