SELECT
Duration = Case
When ([Start_Datetime] <= [MIN_START]) and [End_Datetime] Between [MIN_START] and [MAX_END] Then [MIN_START] - [End_Datetime]
When ([Start_Datetime] <= [MIN_START]) and ([MIN_START] and [MAX_END] ) Between ([Start_Datetime] and [End_Datetime]) Then [MAX_END] - [MIN_START]
When ([Start_Datetime] >= [MAX_END]) and [MAX_END] Between [Start_Datetime] and [End_Datetime] Then [MAX_END] - [Start_Datetime]
When ([Start_Datetime] >= [MAX_END]) and ([Start_Datetime] and [End_Datetime] ) Between ([MIN_START] and [MAX_END] ) Then [End_Datetime] - [Start_Datetime]
Else 0
From DB1
Example [Start_Datetime] [EndTime] [MIN_START][MAX_END] [Result]
1 1 6 2 7 4
2 2 6 3 5 2
3 4 7 3 6 2
4 3 4 2 7 1
我尝试使用And和Between My SQL错误 它说
在上下文中指定的非布尔类型的表达式 条件是预期的,靠近'和'。
我只是想知道如何纠正这个感谢
答案 0 :(得分:0)
我认为在处理日期时间段交叉问题时可以将问题分解为方案。
在你的情况下,我们感兴趣的是这两个时期是否相交,如果是,那么相交的持续时间是多少:
Period 1 (Min_Start to Min_End)
Period 2 (Start_Datetime to End_Datetime)
Scenario1:
P1: <----------->
P2: <----------->
OR
P1: <----------->
P2: <------------>
Du: NULL
WHEN Min_End < Start_Datetime OR Min_Start > End_Datetime THEN NULL
--We can also check the opposite of this (Do these periods intersect?):
WHEN Min_End >= Start_Datetime AND Min_Start <= End_Datetime THEN --THEY INTERSECT!
Scenario2:
P1: <---------------------------->
P2: <--------------------------->
Du: <----------------------->
WHEN Min_Start <= Start_Datetime AND Min_End <= End_DateTime THEN Min_End - Start_Datetime
场景3:
P1: <---------------------------->
P2: <------------->
Du: <------------->
WHEN Min_Start <= Start_Datetime and Min_End > End_Datetime THEN End_Datetime - Start_Datetime
Scenario4:
P1: <----------------------->
P2: <------------->
Du: <---------->
WHEN Min_Start > Start_Datetime AND Min_End > End_Datetime THEN End_Datetime - Min_Start
Scenario5:
P1: <--------------->
P2: <------------------------->
Du: <--------------->
When Min_Start > Start_Datetime AND Min_End < End_Datetime Then Min_End - Min_Start
这可以写成:
CASE
/*S1: Do they intersect?*/
WHEN Min_End >= Start_Datetime AND Min_Start <= End_Datetime
THEN
CASE
/*S2*/ WHEN Min_Start <= Start_Datetime AND Min_End <= End_DateTime THEN DATEDIFF(day, Start_Datetime, Min_End)
/*S3*/ WHEN Min_Start <= Start_Datetime and Min_End > End_Datetime THEN DATEDIFF(day, Start_Datetime, End_Datetime)
/*S4*/ WHEN Min_Start > Start_Datetime AND Min_End > End_Datetime THEN DATEDIFF(day, Min_Start, End_Datetime)
/*S5*/ WHEN Min_Start > Start_Datetime AND Min_End < End_Datetime THEN DATEDIFF(day, Min_Start, Min_End)
END
END
希望这是正确的。这些东西总是让我感到困惑;)
答案 1 :(得分:0)
问题出在你的最后一个条件:
When ([Start_Datetime] >= [MAX_END])
and ([Start_Datetime] and [End_Datetime] )
Between ([MIN_START] and [MAX_END] )
Then [End_Datetime] - [Start_Datetime]
Else 0
您希望通过Between ([MIN_START] and [MAX_END] )
这没有意义,也许你的意思是:
When ([Start_Datetime] >= [MAX_END])
and ([Start_Datetime] Between [MIN_START] and [MAX_END])
and ([End_Datetime] Between [MIN_START] and [MAX_END])
Then [End_Datetime] - [Start_Datetime]
这是最后一个条件
答案 2 :(得分:0)
要确定范围的开始/结束,您只需要将最大开始日期与最小结束日期进行比较。这是一个测试值与问题中的值匹配的示例。
DECLARE @duration1_start INT, @duration1_end INT, @duration2_start INT, @duration2_end INT
-- Test 1: Returns 4
SELECT @duration1_start = 1, @duration1_end = 6, @duration2_start = 2, @duration2_end = 7
-- Test 2: Returns 2
SELECT @duration1_start = 2, @duration1_end = 6, @duration2_start = 3, @duration2_end = 5
-- Test 3: Returns 2
SELECT @duration1_start = 4, @duration1_end = 7, @duration2_start = 3, @duration2_end = 6
-- Test 4: Returns 1
SELECT @duration1_start = 3, @duration1_end = 4, @duration2_start = 2, @duration2_end = 7
SELECT (SELECT MIN(en) FROM (SELECT @duration1_end AS en UNION SELECT @duration2_end)sq) -
(SELECT MAX(st) FROM (SELECT @duration1_start AS st UNION SELECT @duration2_start)sq)
相反,如果您确实想使用datetime字段,可以使用:
DECLARE @duration1_start DATETIME, @duration1_end DATETIME, @duration2_start DATETIME, @duration2_end DATETIME
-- Test 1: Returns 4
SELECT @duration1_start = '1/1/2018', @duration1_end = '1/6/2018', @duration2_start = '1/2/2018', @duration2_end = '1/7/2018'
-- Test 2: Returns 2
SELECT @duration1_start = '1/2/2018', @duration1_end = '1/6/2018', @duration2_start = '1/3/2018', @duration2_end = '1/5/2018'
-- Test 3: Returns 2
SELECT @duration1_start = '1/4/2018', @duration1_end = '1/7/2018', @duration2_start = '1/3/2018', @duration2_end = '1/6/2018'
-- Test 4: Returns 1
SELECT @duration1_start = '1/3/2018', @duration1_end = '1/4/2018', @duration2_start = '1/2/2018', @duration2_end = '1/7/2018'
SELECT DATEDIFF(DAY,
(SELECT MAX(st) FROM (SELECT @duration1_start AS st UNION SELECT @duration2_start)sq),
(SELECT MIN(en) FROM (SELECT @duration1_end AS en UNION SELECT @duration2_end)sq))
如果没有交叉点,您将获得一个负数,因为最大起始值大于最小值。您可以使用case语句处理该场景:
-- Test 5: Returns -1
SELECT @duration1_start = 3, @duration1_end = 4, @duration2_start = 5, @duration2_end = 6
SELECT CASE WHEN diff < 0 THEN NULL ELSE diff END
FROM
(
SELECT (SELECT MIN(en) FROM (SELECT @duration1_end AS en UNION SELECT @duration2_end)sq) -
(SELECT MAX(st) FROM (SELECT @duration1_start AS st UNION SELECT @duration2_start)sq) AS diff
)sq