配对的最佳方式&在SQL数据中发现异常

时间:2012-03-30 11:39:06

标签: sql sql-server

问题是它在SQL中需要很长时间并且必须有更好的方法。我已经选择了下面的场景的缓慢部分。 场景: 两个(临时)表,其中包含必须配对的车辆的开始和结束事件时间,以计算空闲持续时间。问题是缺少一些事件数据。我想出了一个基本的方法,确定最后结束时间是在下一个开始时间之后,并删除无效的开始。再次不优雅+非常慢。

表格:

create table #start(VehicleIp int null,                                         CurrentDate datetime null,
                    EventId int null, 
                    StartId int null)
create table #end(VehicleIp int null, 
        CurrentDate datetime null,
        EventId int null, 
        EndId int null)

- //注意:StartId和EndId都预先填充了类似的内容:

ROW_NUMBER() Over(Partition by VehicleIp order by VehicleIp,  CurrentDate)

- //慢速SQL

while exists(
            select top 1 tOn.EventId 
            from #start as tOn 
            left JOIN #end tOff 
            on tOn.VehicleIp = tOff.VehicleIp and 
            tOn.StartID = tOff.EndID +1
     )
begin

      declare @badEntry int

      select top 1 @badEntry = tOn.EventId  
      from #s as tOn 
            left JOIN #se tOff  
              on tOn.VehicleIp = tOff.VehicleIp and 
                 tOn.StartID = tOff.EndID +1 
       order by tOn.CurrentDate 

       delete from #s where EventId  = @badEntry 

      ;with _s as ( select VehicleIp, CurrentDate, EventId, 
                           ROW_NUMBER() Over(Partition by VehicleIp 
                           order by VehicleIp, CurrentDate) StartID 
                     from #start)
      update #start 
  set StartId = _s.StartId 
  from #s join _s on #s.EventId  = _s.EventId 

end 

1 个答案:

答案 0 :(得分:1)

假设您从包含Vehicle和使用它的间隔的表开始,此查询将识别间隙。

select b.VehicleID, b.IdleStart, b.IdleEnd
from
   (
      select VehicleID, 
       -- If EndDate is not inclusive, remove +1
             EndDate + 1 IdleStart, 
       -- First date after current for this vehicle
       -- If you don't want to show unused vehicles to current date remove isnull part 
             isnull((select top 1 StartDate 
                from TableA a 
               where a.VehicleID = b.VehicleID
                 and a.StartDate > b.StartDate
               order by StartDate
             ), getdate()) IdleEnd
        from TableA b
   ) b
where b.IdleStart < b.IdleEnd

如果日期有时间部分,则应将其截断为所需的精度,此处为日期:

dateadd(dd, datediff(dd,0, getDate()), 0)

用hh,mm或任何需要的精度替换dd。

And here is Sql Fiddle with test