请忍受我。这已经long绕了,我希望我能清楚地遇到。
我有一个表(table1
),其中包含数据类型为[deadline]
的列[completion]
和datetime
。
我需要以分钟为单位计算[deadline]
和[completion]
之间的日期差异。
例如:
结果必须为5。
但是,我还需要使用以前生成的自定义表[tableBH]
来计算银行假期,该表具有[date] [bank holiday name]
。
此外,还有另一个表维护表[tableMaintenance]
,其列为[date] [maintenance reason]
。
最后,我星期一至星期五的工作时间为0900至1900,星期六为1100-1500。
我需要datediff,最好以分钟为单位,以考虑非工作时间,非工作日和银行假期。
理想情况下是通过功能实现的。谁能指出从哪里开始?
我当前的脚本仅执行DATEDIFF ( mi , deadline, completion)
好吧,我这么说,但是目前有点令人费解,但是我以后可以解决。
为了保持透明度,我当前的代码(其中未考虑维护日,银行假期和非工作时间)是
CONVERT(varchar, Datediff(n, [deadline],[completion])/60) + ':' + Right('0' + CONVERT(varchar,(datediff(n,[deadline],[completion]) %60)),2)) as [TimeDIFF]
这种格式没有太大关系。
重要的是引用
帮助?
示例:
TableBH-[日期],[银行假期名称]列
26 November 2018, FakeBH1
TableMaintenance-列[日期],[维护原因]
28 November 2018, FakeMaintenance1
表1-[id],[deadline],[completion]列
输出ID,以分钟为单位的持续时间1 = 10 2 = 4 3 = -25 4 = 20
答案 0 :(得分:0)
创建Bank_Calendar表,该表列出了每个银行日期,并关注工作时间。它包括关闭,休假和零时间维护。
BankDate BankTimeStart BankTimeEnd BankDateDescription
2018-11-19 09:00:00.0000000 19:00:00.0000000 Mon
2018-11-20 09:00:00.0000000 19:00:00.0000000 Tue
2018-11-21 09:00:00.0000000 19:00:00.0000000 Wed
2018-11-22 09:00:00.0000000 19:00:00.0000000 Thu
2018-11-23 09:00:00.0000000 19:00:00.0000000 Fri
2018-11-24 11:00:00.0000000 15:00:00.0000000 Sat
2018-11-25 00:00:00.0000000 00:00:00.0000000 Sun closed
2018-11-26 00:00:00.0000000 00:00:00.0000000 Mon fakeBH1
2018-11-27 09:00:00.0000000 19:00:00.0000000 Tue
2018-11-28 00:00:00.0000000 00:00:00.0000000 Wed fakeMaintenance
2018-11-29 09:00:00.0000000 19:00:00.0000000 Thu
2018-11-30 09:00:00.0000000 19:00:00.0000000 Fri
这是我对table1的演绎,它具有与时间字段分开的日期字段,以使以后的运算更容易
DC_ID Deadline_Date Deadline_Time Completion_Date Completion_Time
1 2018-11-24 14:55:00.0000000 2018-11-27 09:05:00.0000000
2 2018-11-24 15:05:00.0000000 2018-11-27 09:04:00.0000000
3 2018-11-27 11:00:00.0000000 2018-11-27 10:35:00.0000000
4 2018-11-27 16:50:00.0000000 2018-11-29 09:10:00.0000000
5 2018-11-22 09:05:00.0000000 2018-11-22 09:10:00.0000000
这是SQL
select
dc.*
,sum(
Case when dc.Deadline_Date = cal.BankDate and dc.Completion_Date = cal.BankDate Then
--'SameDay'
Datediff(n, dc.Deadline_Time, dc.Completion_Time)
when dc.Deadline_Date = cal.BankDate and dc.Completion_Date <> cal.BankDate
and dc.Deadline_Time > cal.BankTimeEnd Then
--'FR' but Deadline is after Closing
0
when dc.Deadline_Date = cal.BankDate and dc.Completion_Date <> cal.BankDate Then
--'FR' the remaining part of the day until closing
Datediff(n, dc.Deadline_Time, cal.BankTimeEnd)
when dc.Deadline_Date <> cal.BankDate and dc.Completion_Date <> cal.BankDate Then
--'allday' add the entire day (for closings/holidays it becomes zero)
Datediff(n, cal.BankTimeStart, cal.BankTimeEnd)
when dc.Deadline_Date <> cal.BankDate and dc.Completion_Date = cal.BankDate Then
--'TO' add the beginning part of the day
Datediff(n, cal.BankTimeStart, dc.Completion_Time)
End )
as minnn
from DateDiff_DeadlineCompletion as dc
Left Join DateDiff_Calendar as cal
On dc.Deadline_Date <= cal.BankDate
and dc.Completion_Date >= cal.BankDate
Group By dc.DC_ID
,dc.Deadline_Date
,dc.Deadline_Time
,dc.Completion_Date
,dc.Completion_Time
和结果(顺便说一句-我们对项目4有了不同的答案)
DC_ID Deadline_Date Deadline_Time Completion_Date Completion_Time minnn
1 2018-11-24 14:55:00.0000000 2018-11-27 09:05:00.0000000 10
2 2018-11-24 15:05:00.0000000 2018-11-27 09:04:00.0000000 4
3 2018-11-27 11:00:00.0000000 2018-11-27 10:35:00.0000000 -25
4 2018-11-27 16:50:00.0000000 2018-11-29 09:10:00.0000000 140
5 2018-11-22 09:05:00.0000000 2018-11-22 09:10:00.0000000 5
答案 1 :(得分:0)
BankDate BankTimeStart BankTimeEnd WorkingMins
2018-11-19 09:00:00.0000000 19:00:00.0000000 720
2018-11-20 09:00:00.0000000 19:00:00.0000000 720
2018-11-21 09:00:00.0000000 19:00:00.0000000 720
2018-11-22 09:00:00.0000000 19:00:00.0000000 720
2018-11-23 09:00:00.0000000 19:00:00.0000000 720
2018-11-24 09:00:00.0000000 19:00:00.0000000 480
2018-11-25 09:00:00.0000000 19:00:00.0000000 480
2018-11-26 09:00:00.0000000 19:00:00.0000000 480 *(Bank Holiday)*
2018-11-27 09:00:00.0000000 19:00:00.0000000 720
2018-11-28 00:00:00.0000000 00:00:00.0000000 0 *(fakeMaintenance)*
2018-11-29 09:00:00.0000000 19:00:00.0000000 720
2018-11-30 09:00:00.0000000 19:00:00.0000000 720
上表是受@donPablo启发的
实际上,银行假日和星期日现在是上午9点至下午5点。
还有[IsBankHoliday]和[IsNonWorkingDay](通常是维护)两列。
然后我在DimDate过程中添加了以下内容:
CASE
WHEN [nw].[NonWorkingDayDate] IS NOT NULL
THEN '00:00:00'
ELSE '09:00:00'
END AS [StartTime],
CASE
WHEN [nw].[NonWorkingDayDate] IS NOT NULL
THEN '00:00:00'
WHEN [bh].[BankHolidayDate] IS NOT NULL or [DayOfWeekNumber] IN (6,7)
THEN '17:00:00'
ELSE '21:00:00'
END AS [EndTime],
然后,我创建了以下函数:
ALTER FUNCTION [Udf].[GenerateBreachTime] (@CompletionAt [datetime],
@截止日期[日期时间])
SELECT (SELECT
CASE
WHEN @Deadline > @CompletionAt THEN -1
WHEN CONVERT(varchar(8), @Deadline, 112) <= CONVERT(varchar(8), @CompletionAt, 112) THEN CASE --NWD DC|| ||DC = 0
WHEN ([Non Working Day] = 1 AND
CONVERT(varchar(8), @Deadline, 112) = CONVERT(varchar(8), [DateId], 112)) --nwd
OR @Deadline > CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime) --deadline after hours
OR @CompletionAt < CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime) THEN 0
-- D|C|
WHEN @Deadline < CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime) AND
@CompletionAt < CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime) THEN DATEDIFF(n, CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime), @CompletionAt)
--D||C
WHEN @Deadline < CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime) AND
@CompletionAt > CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime) THEN DATEDIFF(n, CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime), CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime))
-- |DC|
WHEN @Deadline >= CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime) AND
@CompletionAt <= CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime) THEN DATEDIFF(n, @Deadline, @CompletionAt)
--|D|C
WHEN @Deadline >= CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime) AND
@CompletionAt > CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime) THEN DATEDIFF(n, @Deadline, CAST(Concat(CONVERT(date, @Deadline), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime))
ELSE 0
END
ELSE 0
END
AS [BreachMins]
FROM [Vw].[Dim Date] DimDate
WHERE dateid = CONVERT(varchar(8), @Deadline, 112))
+ (SELECT
CASE
WHEN CONVERT(varchar(8), @Deadline, 112) >= CONVERT(varchar(8), @CompletionAt, 112) THEN 0
WHEN CONVERT(varchar(8), @Deadline, 112) <= CONVERT(varchar(8), @CompletionAt, 112) THEN CASE
-- C|| OR NWD
WHEN @CompletionAt < CAST(Concat(CONVERT(date, @CompletionAt), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime) OR
([Non Working Day] = 1 AND
CONVERT(varchar(8), @CompletionAt, 112) = CONVERT(varchar(8), [DateId], 112)) THEN 0
-- |C|
WHEN @CompletionAt <= CAST(Concat(CONVERT(date, @CompletionAt), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime)
--THEN 1
THEN DATEDIFF(n, CAST(Concat(CONVERT(date, @CompletionAt), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime), @CompletionAt)
--||C
WHEN @CompletionAt > CAST(Concat(CONVERT(date, @CompletionAt), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime)
--THEN 2
THEN DATEDIFF(n, CAST(Concat(CONVERT(date, @CompletionAt), ' ', CONVERT(char(5), [StartTime], 108)) AS datetime), CAST(Concat(CONVERT(date, @CompletionAt), ' ', CONVERT(char(5), [EndTime], 108)) AS datetime))
ELSE 0
END
ELSE 0
END
AS [BreachMins]
FROM [Vw].[Dim Date] DimDate
WHERE dateid = CONVERT(varchar(8), @CompletionAt, 112))
+ (SELECT
CASE
WHEN SUM(workingminsinday) IS NULL THEN 0
ELSE SUM(workingminsinday)
END AS [x]
FROM vw.[Dim Date]
WHERE dateid BETWEEN CONVERT(varchar(8), @Deadline + 1, 112) AND CONVERT(varchar(8), @CompletionAt - 1, 112))
AS [BreachMins]
日常程序调用该函数
,[BreachTime].[BreachInMins]
FROM [Syn].[X]
CROSS APPLY [udf].[GenerateBreachTime] ([Completed],[Deadline]) [BreachTime]
后续视图处理-1种情况,将其更改为NULL。
我希望这对其他人有帮助,如果还不清楚的话,我们深表歉意。