基于今天获得下一个工作日的算法

时间:2014-02-04 13:15:27

标签: sql sql-server sql-server-2008 tsql

假设今天是星期四。星期三和星期五我有一面旗帜。

如果我创建一个临时表,那么它将看起来像

ID  WeekDay     XFlag
==================================
1   Mon         0    
2   Tue         0    
3   Wed         1    
4   Thu         0    
5   Fri         1    
6   Sat         0    
7   Sun         0

现在,正如我们今天所假设的那样星期四XFlag值为1的第二天是星期五。

任何或所有工作日都可以标记/标记1.但是,我最终希望在今天的基础上获得下一个工作日。因此,对于存储过程中的varchar变量,我的结果将为Fri。 在这里,如果今天结婚,那么结果也将是“星期五”。但如果今天是“星期五”,结果将是“星期三”。所以,请关注此类案件。 我该怎么办?

4 个答案:

答案 0 :(得分:2)

所以你想要第二天,但挑战是周日形成一个周期。你可以使用order by和一些聪明:

来处理这个问题
select top 1 tt.*
from TemporaryTable tt
where flag = 1
order by (7 + tt.id - datepart(dw, getdate())) % 7

Here是一个SQL小提琴。

编辑:

如果datefirst可能设置不同,您可以在日期名称上进行联接。 order by条件稍微复杂一点:

select top 1 tt.*
from TemporaryTable tt cross join
     (select id from TemporaryTable tt where Weekday = left(datepart(dw, getdate()), 3)
     ) as startid
where flag = 1
order by (tt.id - startid.id + 7) % 7;

当然,这假定返回的语言是英语。

答案 1 :(得分:1)

我在这里已经完成了程序,但是如果需要,可以将这些部分合并到一个更大的查询中,而不是使用局部变量:

declare @t table (ID int not null,Weekday char(3) not null,XFlag bit not null)
insert into @t(ID,WeekDay,XFlag) values
(1,'Mon',0),(2,'Tue',0),(3,'Wed',1),
(4,'Thu',0),(5,'Fri',1),(6,'Sat',0), 
(7,'Sun',0)

declare @Today int
declare @NextDay int

--Set today, in a DATEFIRST safe manner
set @Today = ((DATEPART(weekday,CURRENT_TIMESTAMP) + 7) --Today
       - DATEPART(weekday,'20140106') --Known Monday
       ) % 7 + 1

set @NextDay = COALESCE((select MIN(ID) from @t where XFlag = 1 and ID > @Today),
                        (select MIN(ID) from @t where XFlag = 1))

select Weekday from @t where ID = @NextDay

希望(相对)容易看出我的想法。

设置@Today可能是最复杂的部分,这只是因为我正在尝试编写任何人都可以运行的代码,而无需调整它或DATEFIRST设置。我们减去两次调用DATEPART(weekday,...的结果,我们知道其中一个肯定是星期一,我们也设置它以便我们总是产生一个积极的结果。然后我们使用% 7确保它在0-6范围内,对应于星期一到星期日,然后加1,这样表达式生成的值就与表中的ID匹配。 / p>

答案 2 :(得分:1)

@ GordonLinoff的答案略有改进,不依赖于本地日期第一设置

select top 1 *
from <table>
where Xflag = 1
order by datediff(d, id-1, current_timestamp) % 7 desc

答案 3 :(得分:0)

试试这里,WorkingDay是TableName

Select *,
    CASE 
         WHEN
        (Select top 1 WeekDay From WorkingDay WHERE ID > W.ID AND XFLAG=1 ORDER BY ID) IS NOT NULL 
            THEN (Select top 1 WeekDay From WorkingDay WHERE ID > W.ID AND XFLAG=1 ORDER BY ID)
        ELSE
        (Select top 1 WeekDay From WorkingDay WHERE ID < W.ID AND XFLAG=1 ORDER BY ID)
        END AS NextWorkingDay       
    From  WorkingDay   W
    Order By ID