首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >将一个日期范围和在另一个日期范围内

将一个日期范围和在另一个日期范围内
EN

Stack Overflow用户
提问于 2012-11-17 01:11:36
回答 1查看 257关注 0票数 1

尝试用SQL编写以下查询:事件具有开始/结束日期/时间。用户可以在特定时间内使用。如何找到用户可用于特定事件的总时间?

示例:

代码语言:javascript
复制
--Event--
eventID eventStart          eventEnd
1       2012-10-10 15:00    2012-10-10 18:00

--Available--
userID  availStart          availEnd
64      2012-10-10 10:00    2012-10-10 16:00
64      2012-10-10 16:30    2012-10-10 16:40
64      2012-10-10 16:55    2012-10-10 22:00

用户可自由使用135分钟( 15:00-16:00为60分钟,16:30-16:40为10分钟,16:55至18:00为65分钟)。

一些帮助编写SQL将是非常有帮助的,发现这一个棘手!

EN

回答 1

Stack Overflow用户

回答已采纳

发布于 2012-11-17 02:20:15

现在就测试了:http://sqlfiddle.com/#!3/a4e7a/2

我假设了一个用户表。性能改进还有很大的余地。例如,添加一个where子句,消除不重叠的范围。如果用可怕的case语句替换函数,也可能会更快。

棘手之处在于计算出两个时隙中有多少重叠的算法。我总是觉得画出这些案件的图片是有用的:

代码语言:javascript
复制
Case 1
|------|
         |=======|

Case 2
|------|
     |======|

Case 3
|-------|
  |===|

等价物与命令相反。

结果表明,重叠是两个结束时间减去两个开始时间的最大值之后的最小值。(如果为否定,则不存在重叠)。我总是要检查所有的案子才能说服自己。

代码语言:javascript
复制
-- Function that determines how many minutes of overlap there are between two timespans
Create Function dbo.MinutesOverlap(
  @Start1 as datetime, @End1 as datetime, @Start2 as datetime, @End2 as datetime
) Returns int As
Begin
  Declare 
    @MaxStart As datetime,
    @MinEnd As datetime,
    @Ret int = 0

  Set @MaxStart = Case When @Start1 > @Start2 Then @Start1 Else @Start2 End
  Set @MinEnd = Case When @End1 > @End2 Then @End2 Else @End1 End

  If @MaxStart < @MinEnd
    Set @Ret = DateDiff(Minute, @MaxStart, @MinEnd)

  Return @Ret
End


Select
  u.UserID,
  e.EventID,
  Sum(dbo.MinutesOverlap(e.eventStart, e.eventEnd, a.availStart, a.availEnd))
From
  Event e
    Cross Join
  User u
    Left Outer Join
  Available a
    On u.UserID = a.UserID
Group By
  u.UserID, 
  e.EventID
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/13426661

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档