Данные о времени оконной функции SQL Server - PullRequest
0 голосов
/ 22 мая 2018

Я использую SQL Server 2016, и у меня есть набор данных, который выглядит следующим образом

Name    Time                    Type
CL1 2018-05-22 10:50:00 -04:00  SampleAndTrade
CL1 2018-05-22 11:00:00 -04:00  TradeOnly
CL1 2018-05-22 11:10:00 -04:00  TradeOnly
CL1 2018-05-22 11:20:00 -04:00  TradeOnly
CL1 2018-05-22 14:10:00 -04:00  SampleAndTrade
CL1 2018-05-22 14:20:00 -04:00  TradeOnly
CL1 2018-05-22 14:30:00 -04:00  TradeOnly
CL1 2018-05-22 14:40:00 -04:00  TradeOnly
CL1 2018-05-22 14:50:00 -04:00  TradeOnly
HO1 2018-05-22 10:50:00 -04:00  SampleAndTrade
HO1 2018-05-22 11:00:00 -04:00  TradeOnly
HO1 2018-05-22 11:10:00 -04:00  TradeOnly
HO1 2018-05-22 11:20:00 -04:00  TradeOnly
HO1 2018-05-22 14:10:00 -04:00  SampleAndTrade
HO1 2018-05-22 14:20:00 -04:00  TradeOnly
HO1 2018-05-22 14:30:00 -04:00  TradeOnly
HO1 2018-05-22 14:40:00 -04:00  TradeOnly
HO1 2018-05-22 14:50:00 -04:00  TradeOnly

Торговый период начинается с SampleAndTrade и заканчивается TradeOnly (до следующегоSampleAndTrade).У вас всегда будет хотя бы один TradeOnl y после SampleAndTrade.Интервал всегда будет одинаковым для одной сделки.Я хотел бы переместить эти данные так, чтобы они выглядели так:

Name    StartTime    EndTime   IntervalMin
CL1     10:50        11:20     10
CL1     14:10        14:50     10
HO1     10:50        11:20     10
HO1     14:10        14:50     10

Я действительно не могу понять, как правильно разделить данные, чтобы свести их в циклы торговли.Может ли кто-нибудь дать мне подсказку о том, как мне этого добиться?

Ответы [ 4 ]

0 голосов
/ 22 мая 2018

Это должно привести вас туда

declare @t table (Name varchar(20), tm datetime2, Type varchar(20));
insert into @t values 
('CL1', '2018-05-22 10:50:00 -04:00', 'SampleAndTrade'),
('CL1', '2018-05-22 11:00:00 -04:00', 'TradeOnly'),
('CL1', '2018-05-22 11:10:00 -04:00', 'TradeOnly'),
('CL1', '2018-05-22 11:20:00 -04:00', 'TradeOnly'),
('CL1', '2018-05-22 14:10:00 -04:00', 'SampleAndTrade'),
('CL1', '2018-05-22 14:20:00 -04:00', 'TradeOnly'),
('CL1', '2018-05-22 14:30:00 -04:00', 'TradeOnly'),
('CL1', '2018-05-22 14:40:00 -04:00', 'TradeOnly'),
('CL1', '2018-05-22 14:50:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 10:50:00 -04:00', 'SampleAndTrade'),
('HO1', '2018-05-22 11:00:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 11:10:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 11:20:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 14:10:00 -04:00', 'SampleAndTrade'),
('HO1', '2018-05-22 14:20:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 14:30:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 14:40:00 -04:00', 'TradeOnly'),
('HO1', '2018-05-22 14:50:00 -04:00', 'TradeOnly');
with cte as 
( select t1.* 
       , lead(type) over (partition by name order by tm) as nextType
  from @t t1 
)
select t1.Name, t1.tm, min(t2.tm) 
   --, t1.Type, t2.tm, t2.nextType
  from cte t1 
  join cte t2 
    on t1.Name = t2.Name 
   and t1.Type = 'SampleAndTrade' 
   and (t2.nextType = 'SampleAndTrade' or t2.nextType is null)
   and t2.tm > t1.tm
 group by t1.Name, t1.tm
 order by t1.name, t1.tm
0 голосов
/ 22 мая 2018
SELECT
  Name,
  MIN(Time)   AS StartTime,
  MAX(Time)   AS EndTime,
  MIN(Diff)   AS IntervalMin
FROM
(
  SELECT
    *,
    SUM(CASE WHEN type = 'SampleAndTrade' THEN 1 END)
      OVER (PARTITION BY Name
                ORDER BY Time
           )
             AS GroupID,
    DATEDIFF(
      MINUTE,
      LAG(Time)
        OVER (PARTITION BY Name
                  ORDER BY Time
             ),
      Time
    )
      AS Diff
  FROM
    yourTable
)
  AS summary
GROUP BY
  Name,
  GroupID
0 голосов
/ 22 мая 2018

Вы также можете использовать корреляцию подход для более старой версии

with tt as (
 select *, 
       (select count(*) 
        from table 
        where Name = t.name and  [type] = 'SampleAndTrade' and time <= t.time
        ) as Seq
 from table t
)

select Name, min(time), max(time), 
       datediff(minute, min(time), max(time)) as IntervalMin
from tt
group by Name, Seq;
0 голосов
/ 22 мая 2018

Вам просто нужно назначить группу, выполнив кумулятивную сумму 'SampleAndTrade'.Тогда агрегация:

select name, min(time), max(time)
from (select t.*,
             sum(case when type = 'SampleAndTrade' then 1 else 0 end) over (partition by name order by time) as grp
      from t
     ) t
group by name, grp;

Я не уверен, как вычисляется intervalmin.Возможно:

datediff(minute, min(time), max(time)) / count(*)
...