【问题标题】:Adjust Date to match saved day of week调整日期以匹配保存的星期几
【发布时间】:2011-08-22 22:06:14
【问题描述】:

我有一个表,其中存储了 StartDate 和开始日期所在的星期几的名称。我不知道为什么,这是一个糟糕的设计,但我没有创造它,也无法改变它。所以当然,现在我们有一些日期与星期几不匹配。更糟糕的是,星期几是正确的,而开始日期是不正确的。所以我需要做的是调整日期,使每一行的 StartDate 落在该行的 DayOfWeek 上。我们可以假设 StartDate 始终是最小值,因此目标日期将是当前设置的 StartDate 之后的第一个 [DayOfWeek]。

例如,我的行看起来像这样(2010 年 8 月 23 日是星期一,2010 年 8 月 29 日是太阳):

StartDate    DayOfWeek
-----------------------
2010-08-23   Monday
2010-08-23   Tuesday
2010-08-29   Thursday

在第 2 行中,您可以看到日期应该是星期二,但实际上是星期一。我需要结束这个:

StartDate    DayOfWeek
-----------------------
2010-08-23   Monday
2010-08-24   Tuesday
2010-09-02   Thursday

我在处理日期时总是很吃力,但 SQL 也不是我最擅长的技能。谢谢。

【问题讨论】:

    标签: sql tsql date dayofweek


    【解决方案1】:

    窃取 geofftnz 的设置,并希望这是他正在考虑的“聪明”方法:

    declare @baddata table(StartDate datetime, [DayOfWeek] varchar(20))
    insert into @baddata values('2010-08-23','Monday')
    insert into @baddata values('2010-08-23','Tuesday')
    insert into @baddata values('2010-08-29','Thursday')
    
    select * from @baddata
    
    ;with Nums as (
        select 0 as n union all select 1 union all select 2 union all select 3 union all select 4 union all select 5 union all select 6
    )
    update b
    set StartDate = DATEADD(day,Nums.n,StartDate)
    from
        @baddata b
            inner join
        Nums
            on
                DATENAME(weekday,DATEADD(day,Nums.n,StartDate)) = [DayOfWeek]
    
    select * from @baddata
    

    对于第三行,我得到的是 9 月的日期,而不是 8 月,但我认为结果是正确的,而您的示例结果不正确?

    【讨论】:

    • 我喜欢它!我一直在使用我正在尝试的东西挂断 DateFirst 问题。在我的示例中,我确实不小心使用了 8 月而不是 9 月,很抱歉造成混淆。我更正了它,以免其他人有同样的困惑。非常感谢。
    【解决方案2】:

    将有一个聪明的方法来做这件事和“让我们把一些数据扔掉”的方式。这是后者:

    -- here's our bad data we want to fix:
    declare @baddata table(StartDate datetime, [DayOfWeek] varchar(20))
    insert into @baddata values('2010-08-23','Monday')
    insert into @baddata values('2010-08-23','Tuesday')
    insert into @baddata values('2010-08-29','Thursday')
    
    -- we need to create a table containing valid date+day pairs for the 
    -- range of our bad data
    
    -- find max and min dates from our bad data
    declare @MinDate datetime
    declare @MaxDate datetime
    
    select @MinDate = min(StartDate), @MaxDate = max(StartDate) from @baddata
    
    -- offset max date by 7 days (which is the most we'll need to correct the date by)
    set @MaxDate = dateadd(day,7,@MaxDate)
    
    -- create a table matching dates to days
    declare @dates table([Date] Datetime, [DayOfWeek] varchar(20))
    
    declare @i int
    
    -- populate the table with enough days to cover the range of your bad data
    set @i = 0
    while @i <= datediff(day,@MinDate, @MaxDate)
    begin
        insert into @dates
        select dateadd(day, @i, @MinDate), datename(dw,dateadd(day, @i, @MinDate))
    
        set @i = @i + 1
    end
    
    -- show us our table
    select * from @dates
    
    
    -- update the ones with incorrect days
    update bd
    set
        bd.StartDate =  ( -- find the next date with a matching day
            select top 1
                d.[Date]
            from
                @dates d
            where
                d.[DayOfWeek] = bd.[DayOfWeek] and
                d.[Date] >= bd.StartDate
            order by
                d.[Date]
        )
    from
        @baddata bd
            inner join @dates d on 
                d.[Date] = bd.StartDate
    where
        bd.[DayOfWeek] != d.[DayOfWeek] -- date names don't match
    
    select * from @baddata
    

    【讨论】:

    • 非常感谢 geofftnz。这似乎很好地完成了目标。我更喜欢 Damien 的方法,因为它简洁,如果日期范围很大,它似乎更有效。感谢您的帮助和评论。
    • 是的,Damien 的方法看起来更好,尤其是在定期运行的情况下。如果它是一次性的修复工作,那么它就没那么重要了(当然,除非我们谈论的是需要几分钟或几小时才能运行的查询)。
    猜你喜欢
    • 2020-01-21
    • 2018-05-26
    • 2017-10-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2019-05-18
    • 2019-06-02
    相关资源
    最近更新 更多