2016-11-30 54 views
2

最近我碰到一個要求來到了我有我的源表一樣,安裝在設備差的機器SQL Server查詢來獲得繼續OCCURENCES

Machine_Name| Time    | Alarm 
------------|---------------------|--------- 
Mac1  | 2016-11-22 05:15 | 0  
Mac1  | 2016-11-22 05:30 | 1  
Mac1  | 2016-11-22 05:45 | 1  
Mac1  | 2016-11-22 06:00 | 0  
Mac1  | 2016-11-22 06:15 | 1  
Mac1  | 2016-11-22 06:30 | 1  
Mac1  | 2016-11-22 06:45 | 1  
Mac1  | 2016-11-22 07:00 | 1  
Mac1  | 2016-11-22 07:15 | 1  
Mac1  | 2016-11-22 07:30 | 1  
Mac2  | 2016-11-22 05:15 | 0  
Mac2  | 2016-11-22 05:30 | 0  
Mac2  | 2016-11-22 05:45 | 1  
Mac2  | 2016-11-22 06:00 | 1  
Mac2  | 2016-11-22 06:15 | 1  
Mac2  | 2016-11-22 06:30 | 1  
Mac2  | 2016-11-22 06:45 | 0  
Mac2  | 2016-11-22 07:00 | 1  

以上表存儲信息以及對「問題警報」狀態每個時期(每15分鐘一次)。

現在我需要計算這個報警的相關性。對於任何單個報警,相關性爲25%。如果機器連續4個週期(1小時)發出警報,則會將最大相關性歸檔爲100%。

如果連續超過4個連續週期(1小時)發生報警,則相關性保持100%。

預期的結果從上面的源表如下設置,

Machine_Name| Time    | Alarm | Alert_Relevancy(%) 
------------|---------------------|---------|--------------- 
Mac1  | 2016-11-22 05:15 | 0  | 0 
Mac1  | 2016-11-22 05:30 | 1  | 25 
Mac1  | 2016-11-22 05:45 | 1  | 50 
Mac1  | 2016-11-22 06:00 | 0  | 0 
Mac1  | 2016-11-22 06:15 | 1  | 25 
Mac1  | 2016-11-22 06:30 | 1  | 50 
Mac1  | 2016-11-22 06:45 | 1  | 75 
Mac1  | 2016-11-22 07:00 | 1  | 100 
Mac1  | 2016-11-22 07:15 | 1  | 100 
Mac1  | 2016-11-22 07:30 | 1  | 100 
Mac2  | 2016-11-22 05:15 | 0  | 0 
Mac2  | 2016-11-22 05:30 | 0  | 0 
Mac2  | 2016-11-22 05:45 | 1  | 25 
Mac2  | 2016-11-22 06:00 | 1  | 50 
Mac2  | 2016-11-22 06:15 | 1  | 75 
Mac2  | 2016-11-22 06:30 | 1  | 100 
Mac2  | 2016-11-22 06:45 | 0  | 0 
Mac2  | 2016-11-22 07:00 | 1  | 25 

這將是巨大的,如果我還可以得到一個查詢,只選擇那些報警器系列在那裏最低4不斷提高次(相關性達到100)。

預期的第二個結果集如下,我是否已經刪除了任何連續至少4次不是1的報警系列。

Machine_Name| Time    | Alarm | Alert_Relevancy(%) 
------------|---------------------|---------|--------------- 
Mac1  | 2016-11-22 06:15 | 1  | 25 
Mac1  | 2016-11-22 06:30 | 1  | 50 
Mac1  | 2016-11-22 06:45 | 1  | 75 
Mac1  | 2016-11-22 07:00 | 1  | 100 
Mac1  | 2016-11-22 07:15 | 1  | 100 
Mac1  | 2016-11-22 07:30 | 1  | 100 
Mac2  | 2016-11-22 05:45 | 1  | 25 
Mac2  | 2016-11-22 06:00 | 1  | 50 
Mac2  | 2016-11-22 06:15 | 1  | 75 
Mac2  | 2016-11-22 06:30 | 1  | 100 

在此先感謝您的建議/查詢樣本。

問候, RON

+0

什麼DBMS?如果MSSQL 2012+可以使用滯後和主導函數,如果沒有,則可以使用CTE。編輯:假設你是從你以前的問題.. – Matt

+0

你剛剛選擇了一個解決方案,通過一套基於解決方案的記錄記錄。 –

+0

嗨Mortb,對不起,我沒有包括我第一次嘗試的內容。我的錯。我嘗試了CTE方法,但由於我的定位記錄設置錯誤,無法達到確切的結果。但後來LukStorms發佈了我正在尋找的確切解決方案。我會確保我在問題中包含問題片段。謝謝。 –

回答

2
select  Machine_Name 
      ,time 
      ,Alarm 
      ,case when alarm_seq >= 4 then 4 else alarm_seq end * 25 

from  (select  * 
         ,sum (Alarm) over 
         (
          partition by Machine_Name,group_id 
          order by  time 
         )       as alarm_seq 

      from  (select  * 
            ,count (nullif(alarm,1)) over 
            (
             partition by Machine_Name 
             order by  time 
            ) as group_id 

         from  t 
         ) t 
      ) t 

select  Machine_Name 
      ,time 
      ,Alarm 
      ,case when alarm_seq >= 4 then 4 else alarm_seq end * 25 

from  (select  * 
         ,sum (Alarm) over 
         (
          partition by Machine_Name,group_id 
          order by  time 
         )       as alarm_seq 

         ,sum (Alarm) over 
         (
          partition by Machine_Name,group_id 
         )       as alarms 

      from  (select  * 
            ,count (nullif(alarm,1)) over 
            (
             partition by Machine_Name 
             order by  time 
            ) as group_id 

         from  t 
         ) t 
      ) t 

where  alarms >= 4 
     and alarm = 1 
+0

嗨馬克維茲,隨着您的解決方案,作爲CTE解決方案消耗更多的時間來產生結果時,應用於一個大的來源。謝謝。 –

+0

@RonyVarghes - 聽起來像一個很好的舉動......你能分享兩種解決方案的執行時間嗎? –

1

使用CTE與ROW_NUMBER和遞歸CTE

的SQL用來演示表變量。

declare @SourceTable table (Machine_Name varchar(4), [Time] datetime, Alarm bit); 

insert into @SourceTable values 
('Mac1','2016-11-22 05:15',0), 
('Mac1','2016-11-22 05:30',1), 
('Mac1','2016-11-22 05:45',1), 
('Mac1','2016-11-22 06:00',0), 
('Mac1','2016-11-22 06:15',1), 
('Mac1','2016-11-22 06:30',1), 
('Mac1','2016-11-22 06:45',1), 
('Mac1','2016-11-22 07:00',1), 
('Mac1','2016-11-22 07:15',1), 
('Mac1','2016-11-22 07:30',1), 
('Mac2','2016-11-22 05:15',0), 
('Mac2','2016-11-22 05:30',0), 
('Mac2','2016-11-22 05:45',1), 
('Mac2','2016-11-22 06:00',1), 
('Mac2','2016-11-22 06:15',1), 
('Mac2','2016-11-22 06:30',1), 
('Mac2','2016-11-22 06:45',0), 
('Mac2','2016-11-22 07:00',1); 

;with CTE as 
(
    select 
    row_number() over (partition by Machine_Name order by [Time]) as rn, 
    Machine_Name, [Time], Alarm 
    from @SourceTable 
), 
RECURSIVE_CTE as 
(
    select Machine_Name, [Time], Alarm, rn, rn as rn_root, 0 as Relevancy 
    from CTE 
    where Alarm = 0 
    UNION ALL 
    select CTE.Machine_Name, CTE.[Time], CTE.Alarm, CTE.rn, R.rn_root, case when R.Relevancy = 100 then 100 else (R.Relevancy + 25) end 
    from RECURSIVE_CTE R 
    JOIN CTE ON (R.Machine_Name = CTE.Machine_Name AND R.rn + 1 = CTE.rn AND CTE.Alarm = 1) 
) 
select R.Machine_Name, R.[Time], R.Alarm, R.Relevancy as [Alert_Relevancy(%)] 
from RECURSIVE_CTE R 
INNER JOIN (select Machine_Name, rn_root from RECURSIVE_CTE where Relevancy = 100 group by Machine_Name, rn_root) M 
ON (R.Machine_Name = M.Machine_Name and R.rn_root = M.rn_root) 
where R.Relevancy > 0 
order by R.Machine_Name, R.[Time]; 

返回:

Mac1 2016-11-22 06:15:00.000 1 25 
Mac1 2016-11-22 06:30:00.000 1 50 
Mac1 2016-11-22 06:45:00.000 1 75 
Mac1 2016-11-22 07:00:00.000 1 100 
Mac1 2016-11-22 07:15:00.000 1 100 
Mac1 2016-11-22 07:30:00.000 1 100 
Mac2 2016-11-22 05:45:00.000 1 25 
Mac2 2016-11-22 06:00:00.000 1 50 
Mac2 2016-11-22 06:15:00.000 1 75 
Mac2 2016-11-22 06:30:00.000 1 100