【发布时间】:2021-09-22 13:37:50
【问题描述】:
我需要根据输入参数 sdate 和 edate 创建一个包含 Start_Date 和 End_Date 列的临时表。此表是办公室的下班时间列表,包括工作日下午 6 点至早上 6 点。周末我需要时间如下:
- 周五下午 6 点至周六上午 12 点
- 周六上午 12 点至周日上午 12 点和
- 周日上午 12 点至周一上午 6 点
希望下表能让您了解我想要达到的目标:
| Start | Start_Date | End | End_Date |
|---|---|---|---|
| Sun | 08/01/2021 00:00:00.000 | Mon | 08/02/2021 06:00:00.000 |
| Mon | 08/02/2021 18:00:00.000 | Tue | 08/03/2021 06:00:00.000 |
| Tue | 08/03/2021 18:00:00.000 | Wed | 08/04/2021 06:00:00.000 |
| Wed | 08/04/2021 18:00:00.000 | Thu | 08/05/2021 06:00:00.000 |
| Thu | 08/05/2021 18:00:00.000 | Fri | 08/06/2021 06:00:00.000 |
| Fri | 08/06/2021 18:00:00.000 | Sat | 08/07/2021 00:00:00.000 |
| Sat | 08/07/2021 00:00:00.000 | Sun | 08/08/2021 00:00:00.000 |
| Sun | 08/08/2021 00:00:00.000 | Mon | 08/09/2021 06:00:00.000 |
| Mon | 08/09/2021 18:00:00.000 | Tue | 08/10/2021 06:00:00.000 |
| Tue | 08/10/2021 18:00:00.000 | Wed | 08/11/2021 06:00:00.000 |
我已经尝试了以下代码,但它没有得到正确的时间范围。
ALTER PROCEDURE [dbo].[temptableforoffhours]
@BDate varchar(50),
@EDate varchar(50),
@Provider varchar(1000)=''
AS
BEGIN
SET NOCOUNT ON
DECLARE
@BeginDate datetime = '',
@EndDate DATETIME = ''
IF @BeginDate = '' AND @EndDate = ''
BEGIN
SET @BeginDate = DATEADD(YY,-3,GETDATE())
SET @EndDate = GETDATE()
END
IF @BeginDate <> '' AND @EndDate <> ''
BEGIN
Set @BeginDate =CONVERT(datetime, @BDate, 121)
SET @EndDate =Convert (Datetime, cast(CONVERT(DateTime, DATEADD(DD,1,@EDate), 121) as Date),121)
END
/********************************Creation of #tmptimeFrameAudit table with FrameID and Start_day and end_Day********************************/
Declare @CountTimeFrames int = DateDiff(Day, @BeginDate, @EndDate)
DECLARE @Counter INT
SET @Counter = 1
Create Table #tmptimeFrameAudit (Frameid int,Start_Day datetime, End_Day datetime, doW varchar(10))
WHILE ( @Counter <= @CountTimeFrames)
BEGIN
IF @counter = 1
Begin
set @BeginDate = @BeginDate
End
Else
Begin
set @BeginDate = DATEADD(DD,1,@BeginDate)
End
IF (DatePart(weekday,@BeginDate) = 7)
BEGIN
Insert Into #tmptimeFrameAudit values (@Counter,@BeginDate,DATEADD(HOUR,24,@BeginDate), DATENAME(WEEKDAY,@BeginDate))
END
ELSE IF (DatePart(weekday,@BeginDate) = 6)
BEGIN
Insert Into #tmptimeFrameAudit values (@Counter,Dateadd(HOUR,18,CONVERT(datetime, @BeginDate, 121)),DATEADD(HOUR,6,@BeginDate), DATENAME(WEEKDAY,@BeginDate))
END
ELSE IF (DatePart(weekday,@BeginDate) = 1)
BEGIN
Insert Into #tmptimeFrameAudit values (@Counter,@BeginDate,DATEADD(HOUR,30,@BeginDate), DATENAME(WEEKDAY,@BeginDate))
END
ELSE
BEGIN
Insert Into #tmptimeFrameAudit values (@Counter,Dateadd(HOUR,18,CONVERT(datetime, @BeginDate, 121)),DATEADD(HOUR,12,@BeginDate), DATENAME(WEEKDAY,@BeginDate))
END
set @Counter = @Counter+1
END
Select * from #tmptimeFrameAudit
drop Table #tmptimeFrameAudit
END
你能告诉我代码有什么问题并帮助我纠正它吗?谢谢!
【问题讨论】:
-
这里有很多代码味道。一开始所有那些疯狂的约会都是毫无意义的。你设置了一个 datetime = '',然后你检查它是否是你刚刚设置的值,然后你再次检查你设置的值。为什么?你真的应该传入一个日期时间数据类型而不是一个字符串,并假设它是一个有效的日期时间。除此之外,您还需要在这里查看使用计数表而不是循环。那么假期关闭呢?这种事情尖叫需要使用日历表。
-
@BDate varchar(50),不,重新开始。这些应定义为 DATE。不要鼓励容易导致更多问题的草率编码和隐式转换。而且我建议您不要在过程中添加额外的逻辑来“缓解”调用者避免提供日期参数的尝试。抛出一个错误。而这个@BeginDate datetime = ''并不像你想的那样。
标签: sql-server datetime dayofweek date-manipulation