動的

2017-06-01 58 views
0

同じ行の時間差を計算し「DOWN」と、このような「アップ」値に基づいて、同じ列内の行の間のSQLの時間差を算出する方法はあります:動的

enter image description here

3つの(私の知ること)のシナリオがあります

  • 黄色、オレンジとグリーン:STATE_ID(ダウン)2があるとその後STATE_ID 5(アップ)、その時間差ニーズが2つの行の間で計算される。
  • 青:複数のstate_id 2(down)があり、その1つのstate_id 5(up)の後にあるため、最初の行と最後の行の間で時間差を計算する必要があります。
  • 赤:まだ更新されていないため、state_id 2(down)しかないため、月末までの時間差を計算する必要があります。

私があなたを助けてくれることを願っています。

+0

使用しているSQL Serverのバージョンは? –

答えて

1

最初にLAGを使用することを検討していました。

しかしcummulative SUMを使用して、およびMINの窓のバージョンが2つ以上のDOWNのためにも動作します:

-- test reference data 
declare @State table (id int, state varchar(4)); 
insert into @State (id, state) values 
(2,'DOWN'), 
(5,'UP') 

-- test data, using a table variable 
declare @AlertState table (alert_id int identity(1,1), host_id int, state_time datetime, state_id int); 
insert into @AlertState (host_id, state_time, state_id) values 
(119, GetDate()-0.32, 2), 
(119, GetDate()-0.31, 5), 
(119, GetDate()-0.24, 2), 
(119, GetDate()-0.23, 2), 
(119, GetDate()-0.22, 2), 
(119, GetDate()-0.21, 5), 
(119, GetDate()-0.15, 5), 
(119, GetDate()-0.11, 2); 

-- The query 
select alert_id, host_id, state_time, state_id, 
diff_min = (
    case 
    when state_id = 5 then 
    datediff(minute, min(state_time) over (partition by host_id, stategroup), state_time) 
    when state_id = 2 and stategroup is null then 
    datediff(minute, state_time, cast(EOMONTH(GetDate()) as datetime)+1) 
    end), 
s.state 
from (
    select alert_id, host_id, state_time, state_id, 
    sum(case state_id when 5 then 1 end) over (partition by host_id order by state_time desc) as stategroup 
    from @AlertState 
    where state_id in (2,5) 
) q 
left join @State s on s.id = q.state_id 
order by state_time, alert_id; 
0

私は、これは前に

Select a.state_time as downtime, 
    (
     select min(inner.state_time) from tablename downentry where 
     inner.state_time > outer.state_time and downentry.state='UP' 
    ) as uptime 

from tablename upentry 
where state = 'DOWN' 

が次にあなたがそれらの間にDateDiff関数を見つける必要がされなかった、と稼働時間がnullの場合、ダウンタイムと「endofmonth」

間DATEDIFFはそれが潜在的に非常に悪いの道私はいつもデータウェアハウスに答えを書きましたが、求めている結果が得られたと思います。

0

SQL2012 +

あなたは、次の解決策を試みることができる:

SELECT y.group_id, host_id = MIN(host_id), start_time = MIN(state_time), end_time = MAX(state_time), diff_minute = DATEDIFF(MINUTE, MIN(state_time), MAX(state_time)) 
FROM (
    SELECT *, group_id = SUM(x.new_group_start) OVER(ORDER BY x.host_id, x.state_time) 
    FROM (
     SELECT *, new_group_start = IIF(a.state_id = 'DOWN' AND ISNULL(LAG(a.state_id) OVER(ORDER BY a.host_id, a.state_time), 'UP') = 'UP', 1, 0) 
     FROM @Alerts a 
    ) x 
) y 
GROUP BY y.group_id 
ORDER BY y.group_id 

Demo