2012-03-30 8 views
0

問題はSQLに長くかかり、より良い方法が必要であるということです。私はシナリオのために遅い部分を選んだ。 シナリオ: 車両の始動と終わりのためのイベント時間を持つ2つの(一時的な)表で、アイドル時間を数値化する必要があります。問題は、イベントデータの一部が欠落していることです。私は、最終的な終了時刻が次の開始時刻の後であり、無効な開始点を削除することを決定し、最終的な時刻を決定する基本的な方法を考え出しました。再度エレガントではない+非常に遅い。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

Vehicleとそれが使用された間隔を含むテーブルから始めると仮定すると、t彼のクエリはギャップを特定するでしょう。

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

関連する問題