调整日期以匹配保存的星期几

时间:2011-05-11 01:01:43

标签: sql tsql date dayofweek

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

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

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也不是我最强的技能。感谢。

2 个答案:

答案 0 :(得分:3)

将会有一种聪明的方式来实现这一目标,并且“让我们只是抨击一些数据”。以下是后者:

-- 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

答案 1 :(得分:3)

窃取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月份,但我认为结果是正确的,您的样本结果不正确?