2011-01-07 49 views
1

我有一個簡單的SQL Express服務器設置並正在將數據記入日誌中,我有多臺機器(工業機械)正在監控。無論何時機器狀態發生變化,我都會創建一個新的記錄,在以下列中輸入數據。時間(時間標記),機器名稱(文本),狀態(1,2或3),用於運行,空閒和停機,以及原因碼(1-10)。我需要計算機器在每種狀態下的時間以及每種狀態的原因。我想通過SQL報告提供這個功能。這是許多工業製造商目前想要做的功能,我正在試圖創建一個簡單的例子。不幸的是,我不熟悉SQL。我想這可以放在存儲過程中,每隔n秒運行一次以重新計算。非常感激任何的幫助。在SQL中計算機器狀態時間

+0

刪除我的答案,因爲它並沒有解決你的問題根在每個國家所用的時間一欄 - 我誤解了你對你的數據類型的解釋部分 – JNK 2011-01-07 16:52:33

回答

1

您不需要重新計算。您可以根據需要查詢信息。這裏是一個自包含例如

DECLARE @Test 
Table (
    LogTime datetime, 
    MachineName varchar(100), 
    Status int , 
    ReasonCode int) 

INSERT INTO @Test VALUES ('01/01/2011 4:19:11.459' , 'ServerX', 1, 3) 
INSERT INTO @Test VALUES ('01/02/2011 3:43:03.652' , 'ServerZ', 0, 4) 
INSERT INTO @Test VALUES ('02/04/2011 11:17:51.827' , 'ServerX', 2, 2) 
INSERT INTO @Test VALUES ('02/05/2011 4:22:22.205' , 'ServerX', 3, 1) 
INSERT INTO @Test VALUES ('01/03/2011 11:42:44.211' , 'ServerZ', 1, 4) 



;with TIMEdelta AS (
SELECT 
    machineName, 
    t.LogTime, 
    MIN(nextTime) as nextTime 
FROM (
    Select 
     t.MachineName, 
     t.LogTime, 

     t1.LogTime nextTime 
    from @Test t 
     INNER JOIN @Test t1 
     ON t.machineName = t1.machineName 
     AND t.LogTime < t1.LogTime 

    ) t 

GROUP BY 
    machineName, 

    t.LogTime 

) 

SELECT 
    t.MachineName, 
    t.LogTime, 
    t.ReasonCode, 
    t.Status, 
DateDiff(DAY, 0, (TIMEdelta.nextTime - TIMEdelta.LogTime)) Days, 
DatePart(HOUR , TIMEdelta.nextTime - TIMEdelta.LogTime) Hour, 
DatePart(MINUTE, TIMEdelta.nextTime - TIMEdelta.LogTime) MInute 

FROM 

    @Test t 
    LEFT JOIN TIMEdelta 
    ON t.LogTime = timedelta.logtime 
     and t.MachineName = TIMEdelta.MachineName 

此輸出

MachineName LogTime     ReasonCode Status  Days  Hours  Minutes 
----------- ----------------------- ----------- ----------- ----------- ----------- ----------- 
ServerX  2011-01-01 04:19:11.460 3   1   34   6   58 
ServerZ  2011-01-02 03:43:03.653 4   0   1   7   59 
ServerX  2011-02-04 11:17:51.827 2   2   0   17   4 
ServerX  2011-02-05 04:22:22.207 1   3   NULL  NULL  NULL 
ServerZ  2011-01-03 11:42:44.210 4   1   NULL  NULL  NULL 

您可以修改輸出到顯示當前時間 - logTime Description該條而不是空的那些當前狀態行

更新對於可用於樞軸的聚合物可用於PIVOT

SELECT 
MachineName, 
[0] as Started, 
[1] as Stopped, 
[2] as Paused, 
[3] as Foo 

FROM 
(
SELECT 
    t.MachineName, 
    t.status, 
    cast(TimeDelta.nextTime - t.LogTime as DECIMAL(18,10)) duration 

FROM 

    @Test t 
    LEFT JOIN TIMEdelta 
    ON t.LogTime = timedelta.logtime 
    and t.MachineName = TIMEdelta.MachineName 
) source 
PIVOT 
(
SUM(duration) 
FOR status IN ([0], [1], [2], [3]) 
) AS PivotTable; 

具有這種輸出

MachineName Started  Stopped  Paused  Foo 
----------- ------------ -------------- ------------ ------------ 
ServerX  NULL   34.2907449846 0.7114627315 1.0000000000 
ServerZ  1.3331082948 NULL   NULL   ULL 

更新使用日期橫渡個月更新天計算

+0

好的我打算在下面提問,但搞砸了。輸出是否可以添加,這樣我就可以得到每種狀態的總和,所以它只會輸出每臺機器處於每種狀態的總時間? – Bob 2011-01-07 17:31:33

+0

再次感謝你的幫助,這是完美的 – Bob 2011-01-07 19:34:15

2

假設表名爲status

MachineName NVarChar(whatever) 
Status Int 
Reason Int 
Time DateTime 

那麼這個查詢應該很好的工作

Select 
    st.MachineName, 
    st.status, 
    st.reason 
    st.Time as TimeChanged, 
    DateDiff(ss, min(dur.Time), st.Time) 
From 
    Status st inner join 
    Status dur on st.MachineName = dur.MachineName and st.Time <dur.Time 
group by 
    st.MachineName, 
    St.Status, 
    st.Time, 
    st.reason 

編輯 - 在回答您的評論

select 
    st.MachineName, 
    sum(case when status=1 then Duration else 0 end) as RunningTime, 
    sum(case when status=2 then Duration else 0 end) as IdleTime, 
    sum(case when status=3 then Duration else 0 end) as DownTime, 
From 
    (Select 
     st.MachineName, 
     st.status, 
     st.reason 
     st.Time as TimeChanged, 
     DateDiff(ss, min(dur.Time), st.Time) as Duration 
    From 
     Status st inner join 
     Status dur on st.MachineName = dur.MachineName and st.Time <dur.Time 
    group by 
     st.MachineName, 
     St.Status, 
     st.Time, 
     st.reason) as foo 
Group by MachineName 

這應該讓機器名和