2011-12-22 68 views
1

我有一个过程,记录事件何时发生,并假定此事件在接下来的六个小时内有影响。SQL Query根据查找前n行内的值来指定值

表中的数据由Date,Period,BooleanValue组成;如果日期为dd/mm/yyy,则该期间的值为1-48,表示半小时期间(一天中有48天)以及事件是否导致发生(Impact或NotImpact)。作为一个例子,发生于2011年1月5日(期间3)一个单一的事件,因此,该表如下所示:

Date   Period  Event 
    05/01/2011  1   NotImpact 
    05/01/2011  2   NotImpact 
    05/01/2011  3   IMPACT 
    05/01/2011  4   NotImpact 
    05/01/2011  5   NotImpact 

在Excel中,我创建了第四列,并写了一个公式,以查找“打假”在“事件”列中,如果找到,则将接下来的12个半小时标记为“影响”。如果未找到“IMPACT”,则使用默认值“NotImpact”。

=IF(IF(ISERROR(COUNTIF(E2:E13,"IMPACT")),"NotImpact",COUNTIF(E2:E13,"DIS"))>0,"IMPACT","NotImpact") 

应用这个公式,到第四列,会导致它:

Date   Period  Event  ImpactYesNo 
    05/01/2011  1   NotImpact NotImpact 
    05/01/2011  2   NotImpact NotImpact 
    05/01/2011  3   IMPACT  IMPACT 
    05/01/2011  4   NotImpact IMPACT 
    05/01/2011  5   NotImpact IMPACT 
    05/01/2011  6   NotImpact IMPACT 
    05/01/2011  7   NotImpact IMPACT 
    05/01/2011  8   NotImpact IMPACT 
    05/01/2011  9   NotImpact IMPACT 
    05/01/2011  10   NotImpact IMPACT 
    05/01/2011  11   NotImpact IMPACT 
    05/01/2011  12   NotImpact IMPACT 
    05/01/2011  13   NotImpact IMPACT 
    05/01/2011  14   NotImpact IMPACT 
    05/01/2011  15   NotImpact NotImpact 
    05/01/2011  16   NotImpact NotImpact 
    05/01/2011  17   NotImpact NotImpact 

我更喜欢在SQL生成此表(此表驻留在SQL Server 2005盒上)我试图在那里复制这个Excel方法(并且在Python中编写函数),但没有成功。如果有人能帮助我或指出我的方向,我会非常感激。

如果我能回答什么我问任何问题,请不要犹豫,弹出他们的意见

+0

可以跨天事件影响 - 即。如果2011年1月5日第47期有影响,是否影响到2011年1月6日的第10期? – 2011-12-22 13:29:52

+0

如果它发生在第15期,你是否希望它在第二天的第3期运行?或者在一天结束时停止? – gbn 2011-12-22 13:58:29

+0

(1)一个事件可以持续几天,这是非常正确的马克 (2)如果它发生在第15期 - 第15个半小时 - 它将运行到第27期 – 2011-12-22 14:08:26

回答

0

你可以试试这个。它将日期和时间转换为日期时间,然后对此进行一些计算。你必须测试你的数据,看看它的性能是否足够好。

set dateformat dmy 

;with C as 
(
    select dateadd(minute, (Period - 1) * 30, cast([Date] as datetime)) as StartTime, 
     [Date], 
     Period, 
     [Event] 
    from YourTable 
) 
select C1.[Date], 
     C1.Period, 
     C1.[Event], 
     coalesce(C2.[Event], C1.[Event]) as ImpactYesNo 
from C as C1 
    left outer join (select StartTime, 
          dateadd(hour, 6, StartTime) as EndTime, 
          [Event] 
        from C 
        where [Event] = 'IMPACT') as C2 
    on C1.StartTime >= C2.StartTime and 
     C1.StartTime < C2.EndTime    
order by C1.StartTime    

http://data.stackexchange.com/stackoverflow/q/122443/

0
declare @T table 
(
    [Date] varchar(10), 
    Period int, 
    [Event] varchar(9) 
); 

-- shortened to 1 hour periods 
insert into @T 
select '20110501',  1,   'NotImpact' union all 
select '20110501',  2,   'NotImpact' union all 
select '20110501',  3,   'NotImpact' union all 
select '20110501',  4,   'NotImpact' union all 
select '20110501',  5,   'NotImpact' union all 
select '20110501',  6,   'NotImpact' union all 
select '20110501',  7,   'NotImpact' union all 
select '20110501',  8,   'NotImpact' union all 
select '20110501',  9,   'NotImpact' union all 
select '20110501',  10,   'NotImpact' union all 
select '20110501',  11,   'NotImpact' union all 
select '20110501',  12,   'NotImpact' union all 
select '20110501',  13,   'NotImpact' union all 
select '20110501',  14,   'NotImpact' union all 
select '20110501',  15,   'IMPACT' union all 
select '20110501',  16,   'NotImpact' union all 
select '20110501',  17,   'NotImpact' union all 
select '20110501',  18,   'NotImpact' union all 
select '20110501',  19,   'NotImpact' union all 
select '20110501',  20,   'NotImpact' union all 
select '20110501',  21,   'NotImpact' union all 
select '20110501',  22,   'NotImpact' union all 
select '20110501',  23,   'NotImpact' union all 
select '20110501',  24,   'NotImpact' union all 
select '20110601',  1,   'NotImpact' union all 
select '20110601',  2,   'NotImpact' union all 
select '20110601',  3,   'NotImpact' union all 
select '20110601',  4,   'NotImpact' union all 
select '20110601',  5,   'NotImpact' union all 
select '20110601',  6,   'NotImpact' union all 
select '20110601',  7,   'NotImpact' union all 
select '20110601',  8,   'NotImpact' union all 
select '20110601',  9,   'NotImpact' union all 
select '20110601',  10,   'NotImpact' union all 
select '20110601',  11,   'NotImpact' union all 
select '20110601',  12,   'NotImpact' union all 
select '20110601',  13,   'NotImpact' union all 
select '20110601',  14,   'NotImpact' union all 
select '20110601',  15,   'NotImpact' union all 
select '20110601',  16,   'NotImpact' union all 
select '20110601',  17,   'NotImpact' union all 
select '20110601',  18,   'NotImpact' union all 
select '20110601',  19,   'NotImpact' union all 
select '20110601',  20,   'NotImpact' union all 
select '20110601',  21,   'NotImpact' union all 
select '20110601',  22,   'NotImpact' union all 
select '20110601',  23,   'NotImpact' union all 
select '20110601',  24,   'NotImpact'; 

with cte as 
(
    select [Date], Period, [Event], 
    ROW_NUMBER() OVER (ORDER BY [Date], Period) AS rn 
    from @T 
) 
SELECT 
    T1.[Date], T1.Period, 
    ISNULL(T2.[Event], T1.[Event]), 
T1.rn , T2.rn 
FROM 
    cte T1 
    LEFT JOIN 
    cte T2 ON T1.rn BETWEEN T2.rn AND T2.rn + 12 AND T2.[Event] = 'Impact' 
+0

匿名downvote?这是在data.se上测试的。 – gbn 2011-12-22 18:50:02

1
DECLARE 
    @Intervals INT, -- How many periods per day 
    @Lasts INT -- Number of intervals effected 
SELECT 
    @Intervals = 48, 
    @Lasts = 6 

-- Use CTE to calculate continous sequence # 
;WITH SeqImpact ([Date], Period, [Event], Seq) 
AS (Select *, Convert(int, Date) * @Intervals + Period as SEQ from IMPACT) 

SELECT 
    [Date], 
    Period, 
    [Event], 
    CASE (
      SELECT Count(*) 
      FROM SeqImpact History 
      WHERE 
       History.Seq <= SeqImpact.Seq 
       AND History.Seq > SeqImpact.Seq - @Lasts 
       AND [Event] = 'Impact' 
     ) 
     WHEN 0 THEN 'NotImpact' 
     ELSE 'Impact' 
    END 
    AS ImpactYesNo 
FROM SeqImpact