T-SQL脚本 - 时间轴的逻辑问题

Twe*_*fth 5 sql t-sql sql-server sql-server-2000

创建两个临时表然后加载...这是架构.

Create table #SH ([date] datetime,
        sched_id int,
        agent_id int)

Create table #SD (sched_id int,
        start_minute int,
        length int,
        exception_code int)
Run Code Online (Sandbox Code Playgroud)

(遗憾的是,架构和设计是我无法改变的,两个临时表都是从平面文件加载的.如果需要,我可以引入并加载新的临时表).

一点背景 - #SH标题表将人员计划保存为"Start_minute",并以分钟为单位进行"schedule_length".例如,如果开始分钟和时间表长度都是480,那将是上午8点(上午8点=第480分钟),直到下午4点(480分钟后,下午4点=第960分钟)

#SD表保存标头的例外.在上面的示例中,该人可能会有一个午餐例外,即start_minute = 720和30(12:00 - 12:30).

Date和agent_id是我唯一对#SH感兴趣的东西,#sd中的异常信息是我感兴趣的.

此查询有效:

Select [date],#sd.start_minute,#sd.length,#sd.start_minute + #sd.length as 'end_minute',agent_id
from #SH 
inner join #SD on #SD.sched_id = #sh.sched_id
Run Code Online (Sandbox Code Playgroud)

*end_minute最终是start + length = end的计算值

这返回类似于:

   Date     Start  length   end

1 2010-11-11 600    30  630

2 2010-11-11 630    40  670

3 2010-11-11 750    15  765

4 2010-11-11 800    40  840
Run Code Online (Sandbox Code Playgroud)

现在我希望我能说这已经结束并走开......但存在数据输入问题.在第1行和第2行中,第1行的结束时间与第2行中的开始时间对齐,应该合并,因此我的结果如下所示:

Date     Start  length     end

1 2010-11-11 600    70  670

2 2010-11-11 750    15  765

3 2010-11-11 800    40  840
Run Code Online (Sandbox Code Playgroud)

关于如何构建这个逻辑的任何想法让我得到3行而不是4行?我现在正在#sd1.start + #sd1.length =#sd2.start上加入表格.

并且进一步复杂化...上面的例子是需要组合的2行.我遇到了一个连续30分钟的记录,我需要将其记录到一个记录中.幸运的是它们不能重叠(你不会有2条记录占用相同的分钟数),但我认为我上面考虑的连接语句不会起作用.

Stu*_*Stu 2

不需要 CTE,您所需要的只是一个辅助表。创建一次,如下所示:

Create Table DayMinute(Minute Integer)
Declare @M Integer
Set @M = 1
While (@M <= 24*60)
Begin
  Insert Into DayMinute(Minute) Values(@M)
  Set @M = @M + 1
End
Run Code Online (Sandbox Code Playgroud)

然后,你所需要的只是一点技巧:

Select 
  DM.Minute,
  SD.Sched_ID
Into #MinutesWithException
From 
  DayMinute As DM
  Inner Join #SD As SD
    On DM.Minute Between SD.Start_Minute And SD.Start_Minute + Length

Select
  MWE.Sched_ID,
  SH.[Date],
  SH.Agent_ID,
  [Start_Minute] = MWE.Minute,
  [End_Minute] = (Select Min(Last.Minute) -- First one to have no successor
                  From #MinutesWithException As Last
                  Where Last.Sched_ID = MWE.Sched_ID
                    And Last.Minute > MWE.Minute
                    And Not Exists(Select *
                                   From #MinutesWithException As Next
                                   Where Next.Sched_ID = MWE.Sched_iD
                                     And Next.Minute = Last.Minute + 1))
From 
  #MinutesWithException As MWE
  Inner Join #SH As SH
    On MWE.Sched_ID = SH.Sched_ID
Where
  Not Exists(Select * -- All those without predecessor
             From #MinutesWithException As Previous
             Where Previous.Sched_ID = MWE.Sched_ID
               And Previous.Minute = MWE.Minute - 1)
Run Code Online (Sandbox Code Playgroud)

请记住,许多 SQL 问题可以通过重新措辞来解决。不要问“哪些范围没有间隔”,而要问“哪些分钟有间隔”。剩下的就从那里开始。