如何将一周(200851)转换为日期(2008-12-27)?

Fet*_*Fet 2 sql t-sql sql-server date-arithmetic

我如何将一年周(例如0852或200852)转换为日期(例如2008-12-31或特别是周末结束日,即2008-12-27周六或周开始日,即2008-12-21 )?星期五,星期六,星期日或星期一,星期结束的任何一天都会.

Mat*_*lie 5

MS SQL SERVER有DATEADD功能,应该有帮助......

DECLARE @date_string NCHAR(6)
SELECT  @date_string = N'200852'

SELECT DATEADD(
           WEEK,
           CAST(RIGHT(@date_string, 2) AS INT),
           DATEADD(
               YEAR,
               CAST(LEFT(@date_string, 4) AS INT) - 1900,
               0
           )
       )
Run Code Online (Sandbox Code Playgroud)

编辑:

对不起,错过了关于星期六等等的一点......

获得该值后,使用DATEPART获取一周中的哪一天,并从您的答案中减去...

DECLARE @new_date DATETIME
SELECT  @new_date = '2008 Dec 30'

SELECT DATEADD(DAY, 1-DATEPART(dw, @new_date), @new_date)
Run Code Online (Sandbox Code Playgroud)

这会将值带到一周的开始,具体取决于您将DATEFIRST设置为的值.


Wal*_*tty 5

如果这很重要的话,这是一个几乎独立于数据库的解决方案。

创建一个名为 ALMANAC、主键 DATE 的表,其中列出了您计划使用的日期的所有属性。其中一个可能是“年”,另一个可能是“周”。您可以包含您想要经常使用的 DATE 的任何可计算函数。您还可以包含公司特定的 DATE 属性,例如该日期是否是公司假期。

编写一个程序来填充 DATE 10 年(大约 3650 行加上一些闰年)。该程序将使用 DBMS 或某种编程语言中可用的环境特定日期函数。一旦填充了 ALMANAC 表,就可以像普通数据一样使用它。将主键与数据库中的任何日期字段连接起来。

事实证明,这对于几乎自动地按周、按月、按季度和按年准备报告等事情非常有用。

如果 DATE 的粒度不够细,您甚至可以将年历划分为更小的时间单位,例如轮班,其中 3 个班次为一天。


Luk*_*rms 5

我为此目的创建了一个UDF 。它将 YYYYWW 字符串或数字转换为日期。

CREATE FUNCTION dbo.GetDateFromYearWeek (
 @YearWeek VARCHAR(7) = '000101', -- default
 @WeekDay INT = 1, -- default
 @FirstWeekDayName VARCHAR(9) = 'mon' -- default
) RETURNS DATE
BEGIN

 IF @YearWeek = '000101'
   SET @YearWeek = CONCAT(DATEPART(year, GETDATE()), '-', DATEPART(week, GETDATE()));

 IF @YearWeek NOT LIKE '[0-9][0-9][0-9][0-9]%[0-9-][0-9]'
   RETURN NULL;

 IF @WeekDay < 1 OR @WeekDay > 7
   RETURN NULL;

 DECLARE @FirstWeekDay INT = CHARINDEX(LOWER(LEFT(@FirstWeekDayName,3)), '   montuewedthufrisatsun')/3;
 IF @FirstWeekDay = 0 -- not found in string
   SET @FirstWeekDay = @@DATEFIRST;

 DECLARE @Year INT = TRY_CAST(LEFT(@YearWeek, 4) AS INT);
 DECLARE @Week INT = ABS(TRY_CAST(RIGHT(@YearWeek, 2) AS INT));

 DECLARE @Date DATE = TRY_CAST(CONCAT(@Year,'-01-01') AS DATE);
 SET @Date = DATEADD(week, @Week-1, @Date);

 DECLARE @DowDiff INT = (6-@FirstWeekday+@@DATEFIRST+DATEPART(weekday,@Date))%7;
 SET @Date = DATEADD(day, -@DowDiff, @Date);
 SET @Date = DATEADD(day, @WeekDay-1, @Date);

 RETURN @Date;
END;
Run Code Online (Sandbox Code Playgroud)

用法示例:

SELECT *
, [StartOfWeek_SundayFirst] = dbo.GetDateFromYearWeek(col, 1, 'sun')
, [StartOfWeek_MondayFirst] = dbo.GetDateFromYearWeek(col, 1, 'mon')

, [EndOfWeek_SundayFirst]   = dbo.GetDateFromYearWeek(col, 7, 'sunday')
, [EndOfWeek_MondayFirst]   = dbo.GetDateFromYearWeek(col, 7, 'monday')
FROM (VALUES (202201), (202202)) q(col)
ORDER BY 1;
Run Code Online (Sandbox Code Playgroud)
StartOfWeek_SundayFirst StartOfWeek_MondayFirst EndOfWeek_SundayFirst EndOfWeek_MondayFirst
202201 2021-12-26 2021-12-27 2022-01-01 2022-01-02
202202 2022-01-02 2022-01-03 2022-01-08 2022-01-09

db<>fiddle上测试它。

ISO_WEEK 版本

CREATE FUNCTION dbo.GetDateFromIsoYearWeek (
 @YearWeek VARCHAR(7) = '0000-00', -- default
 @WeekDay INT = 1 -- default
) RETURNS DATE
BEGIN

 IF @YearWeek = '0000-00'
   SET @YearWeek = CONCAT(DATEPART(year, GETDATE()), '-', DATEPART(iso_week, GETDATE()));

 IF @YearWeek NOT LIKE '[0-9][0-9][0-9][0-9]%[0-9-][0-9]'
   RETURN NULL;

 IF @WeekDay < 1 OR @WeekDay > 7
   RETURN NULL;

 DECLARE @FirstWeekDay INT = 1; -- monday
 DECLARE @Year INT = TRY_CAST(LEFT(@YearWeek, 4) AS INT);
 DECLARE @Week INT = ABS(TRY_CAST(RIGHT(@YearWeek, 2) AS INT));

 DECLARE @Date DATE = TRY_CAST(CONCAT(@Year,'-01-08') AS DATE);
 SET @Date = DATEADD(week, @Week - 2 + (DATEPART(week, @Date)-(DATEPART(iso_week, @Date))), @Date);

 DECLARE @DowDiff INT = (6-@FirstWeekday+@@DATEFIRST+DATEPART(weekday,@Date))%7;
 SET @Date = DATEADD(day, -@DowDiff, @Date);
 SET @Date = DATEADD(day, @WeekDay-1, @Date);

 RETURN @Date;
END;
Run Code Online (Sandbox Code Playgroud)
DECLARE @Test TABLE ([column] char(7));
INSERT INTO @Test VALUES
  ('2020-53'), ('2021-01'), ('2021-02')
, ('2021-48')
, ('2021-53'), ('2022-01'), ('2022-02')
;

SELECT [column]
, [FirstOfWeek] = dbo.GetDateFromIsoYearWeek([column], 1)
, [LastOfWeek]  = dbo.GetDateFromIsoYearWeek([column], 7)
FROM @Test
ORDER BY 1;
Run Code Online (Sandbox Code Playgroud)
柱子 第一周 最后一周
2020-53 2020-12-28 2021-01-03
2021-01 2021-01-04 2021-01-10
2021年02月 2021-01-11 2021-01-17
2021-48 2021-11-29 2021-12-05
2021-53 2022-01-03 2022-01-09
2022年01月 2022-01-03 2022-01-09
2022年02月 2022-01-10 2022-01-16

db<>fiddle上测试它。