合并未使用的时隙

时间:2012-08-23 09:47:13

标签: sql sql-server-2008

我有一个像

这样的查询结果
|----------------------------------------------|
|StaffId|BranchId|StartTime|EndTime |PatientId |
|----------------------------------------------|
|1      |1       |09:30:00 |09:35:00|Null      |
|1      |1       |09:35:00 |09:40:00|Null      |
|1      |1       |09:40:00 |09:55:00|1         |
|1      |1       |09:55:00 |10:00:00|Null      |
|1      |1       |10:00:00 |10:05:00|Null      |
|1      |1       |10:05:00 |10:20:00|2         |
|1      |1       |10:20:00 |10:25:00|NULL      |
|1      |1       |10:25:00 |10:40:00|3         |
|1      |1       |10:40:00 |10:45:00|Null      |
|1      |1       |10:45:00 |10:50:00|Null      |
|1      |1       |10:50:00 |10:55:00|Null      |
|1      |1       |10:55:00 |11:00:00|Null      |
|----------------------------------------------|

但我希望能够将所有未使用的时间段(没有患者ID的时间段)分组,结果是

|----------------------------------------------|
|StaffId|BranchId|StartTime|EndTime |PatientId |
|----------------------------------------------|
|1      |1       |09:30:00 |09:40:00|Null      |
|1      |1       |09:40:00 |09:55:00|1         |
|1      |1       |09:55:00 |10:05:00|Null      |
|1      |1       |10:05:00 |10:20:00|2         |
|1      |1       |10:20:00 |10:25:00|NULL      |
|1      |1       |10:25:00 |10:40:00|3         |
|1      |1       |10:40:00 |11:00:00|Null      |
|----------------------------------------------|

不确定如何做到这一点,任何指导都将不胜感激。不确定它是否更容易,但查询的结果是通过加入一个只有5分钟间隔的表与患者使用sql获得

INSERT INTO @Results(BranchId, StaffId, StartTime, EndTime)
SELECT us.BranchId, us.StaffId, us.StartTime, us.EndTime
FROM @UnusedSlots us
    left join @Results r
        on (NOT ((r.StartTime >= us.EndTime)
            OR (r.EndTime <= us.StartTime))) AND
            (us.StaffId = r.StaffId)
    where r.BranchId is Null

其中@UnusedSlots是可用的5分钟插槽,而@Results包含预订的插槽(带有患者ID)。如果有办法在这个陈述中建立合并,那就更好了。

我认为如果我可以在没有PatientId的情况下隔离相邻的结果,我可以使用Min(StartTime)Max(EndTime)但是我不知道该如何做到这一点,我最后会得到一个已于09:30至11:00合并

2 个答案:

答案 0 :(得分:3)

select 
    StaffId,
    BranchId,
    MIN(StartTime),
    MAX(EndTime),
    PatientId
from
(
select *,       
    ROW_NUMBER() over (order by starttime) 
      - ROW_NUMBER() over (partition by isnull(PatientID,-1) order by starttime) rn     
from @results
) v
group by staffid, branchid, patientid, rn
order by MIN (starttime)

我不确定StaffID和BranchID在@results表中是否会有所不同,所以如果可以,你可能需要调整它。

答案 1 :(得分:0)

你可以使用光标,虽然性能不会很好地扩展:

    create table #tempTimes (
        staffid int,
        branchid int,
        startTime datetime,
        endTime datetime,
        patientid int)

    insert into #temptimes values (1,1,'2012-09-09 09:30', '2012-09-09 09:35', null)
    insert into #temptimes values (1,1,'2012-09-09 09:35', '2012-09-09 09:40', null)
    insert into #temptimes values (1,1,'2012-09-09 09:40', '2012-09-09 09:45', null)
    insert into #temptimes values (1,1,'2012-09-09 09:45', '2012-09-09 09:55', 1)
    insert into #temptimes values (1,1,'2012-09-09 09:55', '2012-09-09 10:00', null)
    insert into #temptimes values (1,1,'2012-09-09 10:00', '2012-09-09 10:05', null)
    insert into #temptimes values (1,1,'2012-09-09 10:05', '2012-09-09 10:20', 2)

    declare @currentPeriodStart datetime
    declare @currentPeriodEnd datetime
    declare @startTime datetime
    declare @endTime datetime
    declare @lastEndTime datetime
    declare @patientId int

    declare myCurs cursor for select startTime, endTime, patientid from #tempTimes order by startTime 

    open myCurs

    fetch next from myCurs into @startTime, @endTime, @patientId

    while @@fetch_status = 0
    begin
        if @patientId is null
        begin
            if (@currentPeriodStart is null)
                set @currentPeriodStart = @startTime

            set @currentPeriodEnd = @endTime
        end else
        begin
            print   cast(@currentPeriodStart as nvarchar) + ' to ' + cast(@currentPeriodEnd as nvarchar)
            set @currentPeriodStart = null
        end

        fetch next from myCurs into @startTime, @endTime, @patientId
    end

    close myCurs
    deallocate myCurs