SQL Query基于在先前的n行中查找值来指定值

时间:2011-12-22 13:09:56

标签: sql sql-server-2005

我有一个进程记录事件发生的时间,并假设此事件在接下来的六个小时内有影响。

表格包含Date,Period,BooleanValue等数据;如果日是dd / mm / yyyy,则Period是值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中编写函数),但没有成功。如果有人可以帮助我或指出我正确的方向,我真的很感激。

如果我可以回答有关我的要求的任何其他问题,请不要犹豫,在评论中弹出它们

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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/

答案 2 :(得分: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'