根据周数和天数字段设置SQL日期字段值

时间:2018-11-02 14:23:05

标签: sql sql-server date-arithmetic

是否存在基于星期值和日期值设置“日期”值的过程或方法。

要进一步详细说明该日历年,请执行以下操作: 1月1日至7日为第1周, 1月8日至14日是第2周,依此类推。

关于天数值; 星期一是1 星期二是2 星期三是3 星期四是4 星期五是5。

使用这种逻辑,我希望创建并填充一个使用这些值的日期字段。

例如,我希望在Week:2-Day:3填充新日期字段为10/1/2018

任何帮助和指导将不胜感激。

3 个答案:

答案 0 :(得分:2)

使用datetime函数可以完成某些事情,仅根据星期数和工作日数来计算日期。

但是,请注意,@@DATEFIRST在服务器上可能会有所不同。
定义哪个工作日是一周中的第一天。
因此,最好在您的会话中将其更改为1,以使星期一成为第一个工作日。
没有它,可能需要在下面使用的计算中进行调整。
例如,[Weekday]+1返回7时select @@DATEFIRST

示例代码段

declare @Table table ([Week] int, [Weekday] int);

insert into @Table ([Week], [Weekday]) values
 (1, 1)
,(1, 7)
,(2, 1)
,(2, 7)
;

-- The US default for @@DATEFIRST is 7, which would make Sunday weekday 1. 
-- By setting @@DATEFIRST to 1 then Monday will be weekday 1
SET DATEFIRST 1; 

SELECT [Week], [Weekday],
DATEADD(WEEKDAY, 1-DATEPART(WEEKDAY, DATEFROMPARTS(DATEPART(YEAR,GetDate()),1,1)), DATEADD(WEEK,[Week]-1, DATEFROMPARTS(DATEPART(YEAR,GetDate()),1,[Weekday]))) AS CalcDate
FROM @Table
ORDER BY [Week], [Weekday];

结果:

Week Weekday CalcDate
---- ------- ----------
   1       1 2018-01-01
   1       7 2018-01-07
   2       1 2018-01-08
   2       7 2018-01-14

请注意,年份是基于当前日期的。

但是要更新现有表吗?
然后您可以用另一种方式看它。
创建一个包含当年所有日期的临时表,然后从这些日期中导出星期和星期几。
然后,您可以使用该临时表更新现有表。

示例代码段

-- Create a temporary table
IF OBJECT_ID('tempdb..#tmpDates') IS NOT NULL DROP TABLE #tmpDates;
CREATE TABLE #tmpDates ([Week] INT NOT NULL, [WeekDay] INT NOT NULL, [Date] DATE NOT NULL, PRIMARY KEY ([Week], [WeekDay]));

-- Make Monday the first weekday
SET DATEFIRST 1;

-- Filling the temp table with data
WITH DATES2018 AS
(
  SELECT CAST('2018-01-01' AS DATE) AS [Date]
  UNION ALL
  SELECT DATEADD(day, 1, [Date])
  FROM DATES2018
  WHERE [Date] < CAST('2018-12-31' AS DATE)
)
INSERT INTO #tmpDates ([Date], [Week], [WeekDay])
SELECT [Date], DATEPART(WEEK, [Date]) AS [Week], DATEPART(WEEKDAY, [Date]) as [WeekDay]
FROM DATES2018
ORDER BY [Week], [WeekDay]
OPTION (MAXRECURSION 366);


-- Just using a table variable per demonstration
declare @YourTable table ([Week] int, [Weekday] int, [Date] DATE);
-- Sample data
insert into @YourTable ([Week], [Weekday]) values
 (1, 1)
,(1, 7)
,(2, 1)
,(2, 7)
;

-- update based on the temp table
update t
set [Date] = tmp.[Date]
from @YourTable t 
join #tmpDates tmp on (tmp.[Week] = t.[Week] AND tmp.[WeekDay] = t.[Weekday])
where (t.[Date] is null OR t.[Date] <> tmp.[Date]);

select * from @YourTable;

答案 1 :(得分:1)

您可以引用此链接,其中包含日历表创建语句 https://www.sqlshack.com/designing-a-calendar-table/

您需要做的就是将可用的列(例如年,周和日)映射到日历表并提取日期

答案 2 :(得分:1)

也许这样可以帮助您入门。
它会从您的样本中返回日期,但我并未在所有情况下都进行过测试...
因此,我确定它需要进行一些微调,并使用Calender Table,就像@ Ajan-Balakumaran所说的那样会好得多

declare @year int = datepart(year, getdate())
declare @month int
declare @week int = 2
declare @day int = 3

SELECT @month = DATEPART(MM,CAST(CONVERT(CHAR(3),
                         DATEADD(WW, @WEEK - 1,
                         CONVERT(datetime, '01/01/' + CONVERT(char(4) ,@Year)))
                         , 100) + ' 1900' AS DATETIME))

select datefromparts(2018, @month, @day + (@week - 1) * 7)