Don't like ads? PRO users don't see any ads ;-)
Guest

Untitled

By: a guest on Jun 17th, 2012  |  syntax: None  |  size: 6.60 KB  |  hits: 18  |  expires: Never
download  |  raw  |  embed  |  report abuse  |  print
Text below is selected. Please press Ctrl+C to copy to your clipboard. (⌘+C on Mac)
  1. Get list with start and end values from table of datetimes
  2. DeviceID      Timestamp            Value
  3. ----------------------------------------
  4. Device1       1.1.2011 10:00:00    3
  5. Device1       1.1.2011 10:00:01    4
  6. Device1       1.1.2011 10:00:02    4
  7. Device1       1.1.2011 10:00:04    3
  8. Device1       1.1.2011 10:00:05    4
  9. Device1       1.1.2011 14:23:14    8
  10. Device1       1.1.2011 14:23:15    7
  11. Device1       1.1.2011 14:23:17    4
  12. Device1       1.1.2011 14:23:18    2
  13.        
  14. DeviceID      Started              Ended
  15. Device1       1.1.2011 10:00:00    1.1.2011 10:00:05
  16. Device1       1.1.2011 14:23:14    1.1.2011 14:23:18
  17.        
  18. -- Table var to store the gaps
  19. declare @T table
  20. (
  21.   DeviceID varchar(10),
  22.   PrevPeriodEnd datetime,
  23.   NextPeriodStart datetime
  24. )
  25.  
  26. -- Get the gaps
  27. ;with cte as
  28. (
  29.   select *,
  30.     row_number() over(partition by DeviceID order by Timestamp) as rn
  31.   from data
  32. )
  33. insert into @T
  34. select
  35.   C1.DeviceID,
  36.   C1.Timestamp as PrevPeriodEnd,
  37.   C2.Timestamp as NextPeriodStart
  38. from cte as C1
  39.   inner join cte as C2
  40.     on C1.rn = C2.rn-1 and
  41.        C1.DeviceID = C2.DeviceID and
  42.        datediff(s, C1.Timestamp, C2.Timestamp) > 5
  43.  
  44. -- Build islands from gaps in @T
  45. ;with cte1 as
  46. (
  47.   -- Add first and last timestamp to gaps
  48.   select DeviceID, PrevPeriodEnd, NextPeriodStart
  49.   from @T
  50.   union all
  51.   select DeviceID, max(TimeStamp) as PrevPeriodEnd, null as NextPeriodStart
  52.   from data
  53.   group by DeviceID
  54.   union all
  55.   select DeviceID, null as PrevPeriodEnd, min(TimeStamp) as PrevPeriodEnd
  56.   from data
  57.   group by DeviceID
  58. ),
  59. cte2 as
  60. (
  61.   select *,
  62.     row_number() over(partition by DeviceID order by PrevPeriodEnd) as rn
  63.   from cte1
  64. )
  65. select
  66.   C1.DeviceID,
  67.   C1.NextPeriodStart as PeriodStart,
  68.   C2.PrevPeriodEnd as PeriodEnd
  69. from cte2 as C1
  70.   inner join cte2 as C2
  71.     on C1.DeviceID = C2.DeviceID and
  72.        C1.rn = C2.rn-1
  73. order by C1.DeviceID, C1.NextPeriodStart
  74.        
  75. create table Measures (
  76.     DeviceID int not null,
  77.     Occurred datetime not null,
  78.     Value int not null,
  79.     constraint PK_Measures PRIMARY KEY (DeviceID,Occurred)
  80. )
  81. go
  82. insert into Measures (DeviceID,Occurred,Value)
  83. select 1,'2011-01-01T10:00:00',3 union all
  84. select 1,'2011-01-01T10:00:01',4 union all
  85. select 1,'2011-01-01T10:00:02',4 union all
  86. select 1,'2011-01-01T10:00:04',3 union all
  87. select 1,'2011-01-01T10:00:05',4 union all
  88. select 1,'2011-01-01T14:23:14',8 union all
  89. select 1,'2011-01-01T14:23:15',7 union all
  90. select 1,'2011-01-01T14:23:17',4 union all
  91. select 1,'2011-01-01T14:23:18',2
  92.        
  93. ;with StartPeriods as (
  94.     select m1.DeviceID,m1.Occurred as Started
  95.     from Measures m1 left join Measures m2 on m1.DeviceID = m2.DeviceID and m2.Occurred < m1.Occurred and DATEDIFF(second,m2.Occurred,m1.Occurred) < 6
  96.     where m2.DeviceID is null
  97. ), ExtendPeriods as (
  98.     select DeviceID,Started,Started as Ended from StartPeriods
  99.     union all
  100.     select
  101.         ep.DeviceID,ep.Started,m2.Occurred
  102.     from
  103.         ExtendPeriods ep
  104.             inner join
  105.         Measures m2
  106.             on
  107.                 ep.DeviceID = m2.DeviceID and
  108.                 ep.Ended < m2.Occurred and
  109.                 DATEDIFF(SECOND,ep.Ended,m2.Occurred) < 6
  110. )
  111. select DeviceID,Started,MAX(Ended) from ExtendPeriods group by DeviceID,Started
  112.        
  113. select DeviceID,MIN(Timestamp),MAX(Timestamp)
  114.           from @table group by DATEPART(hh,Timestamp),DeviceID
  115.        
  116. WITH data (DeviceID, Timestamp, Value) AS (
  117.   SELECT 'Device1', CAST('1.1.2011 10:00:00' AS datetime), 3 UNION ALL
  118.   SELECT 'Device1',      '1.1.2011 10:00:01',              4 UNION ALL
  119.   SELECT 'Device1',      '1.1.2011 10:00:02',              4 UNION ALL
  120.   SELECT 'Device1',      '1.1.2011 10:00:04',              3 UNION ALL
  121.   SELECT 'Device1',      '1.1.2011 10:00:05',              4 UNION ALL
  122.   SELECT 'Device1',      '1.1.2011 14:23:14',              8 UNION ALL
  123.   SELECT 'Device1',      '1.1.2011 14:23:15',              7 UNION ALL
  124.   SELECT 'Device1',      '1.1.2011 14:23:17',              4 UNION ALL
  125.   SELECT 'Device1',      '1.1.2011 14:23:18',              2
  126. ),
  127. ranked AS (
  128.   SELECT
  129.     *,
  130.     rn = ROW_NUMBER() OVER (PARTITION BY DeviceID ORDER BY Timestamp)
  131.   FROM data
  132. ),
  133. starts AS (
  134.   SELECT
  135.     r1.DeviceID,
  136.     r1.Timestamp,
  137.     rank = ROW_NUMBER() OVER (PARTITION BY r1.DeviceID ORDER BY r1.Timestamp)
  138.   FROM ranked r1
  139.     LEFT JOIN ranked r2 ON r1.DeviceID = r2.DeviceID
  140.       AND r1.rn = r2.rn + 1
  141.       AND r1.Timestamp <= DATEADD(second, 5, r2.Timestamp)
  142.   WHERE r2.DeviceID IS NULL
  143. ),
  144. ends AS (
  145.   SELECT
  146.     r1.DeviceID,
  147.     r1.Timestamp,
  148.     rank = ROW_NUMBER() OVER (PARTITION BY r1.DeviceID ORDER BY r1.Timestamp)
  149.   FROM ranked r1
  150.     LEFT JOIN ranked r2 ON r1.DeviceID = r2.DeviceID
  151.       AND r1.rn = r2.rn - 1
  152.       AND r1.Timestamp >= DATEADD(second, -5, r2.Timestamp)
  153.   WHERE r2.DeviceID IS NULL
  154. )
  155. SELECT
  156.   s.DeviceID,
  157.   Started = s.Timestamp,
  158.   Ended = e.Timestamp
  159. FROM starts s
  160.   INNER JOIN ends e ON s.DeviceID = e.DeviceID AND s.rank = e.rank
  161.        
  162. SELECT a.TS AS [StartTime], (SELECT TOP 1 c.TS FROM TestTime c WHERE c.TS >= a.TS AND
  163.     NOT EXISTS(SELECT * FROM TestTime d WHERE d.TS > c.TS AND DATEDIFF(SECOND, c.TS, d.TS) <= 5) ORDER BY c.TS) AS [StopTime]
  164. FROM TestTime a WHERE NOT EXISTS (SELECT * FROM TestTime b WHERE a.TS > b.TS AND DATEDIFF(SECOND, b.TS, a.TS) <= 5)
  165.        
  166. DECLARE @t TABLE
  167. (DeviceID      VARCHAR(10),
  168.  [Timestamp]    DATETIME,
  169.  VALUE          INT
  170. )
  171.  
  172. INSERT @t
  173. SELECT 'Device1','20110101 10:00:00',    3
  174. UNION SELECT 'Device1','20110101 10:00:01',    4
  175. UNION SELECT 'Device1','20110101 10:00:02',    4
  176. UNION SELECT 'Device1','20110101 10:00:04',   3
  177. UNION SELECT 'Device1','20110101 10:00:05',    4
  178. UNION SELECT 'Device1','20110101 14:23:14',    8
  179. UNION SELECT 'Device1','20110101 14:23:15',    7
  180. UNION SELECT 'Device1','20110101 14:23:17',    4
  181. UNION SELECT 'Device1','20110101 14:23:18',    2
  182.  
  183.  
  184. ;WITH myCTE
  185. AS
  186. (
  187.     SELECT DeviceID, [Timestamp],
  188.            ROW_NUMBER() OVER (PARTITION BY DeviceID
  189.                               ORDER BY [TIMESTAMP]
  190.                              ) AS rn
  191.     FROM @t
  192. )
  193. , recCTE
  194. AS
  195. (
  196.     SELECT DeviceID, [Timestamp],  0 as groupID, rn FROM myCTE
  197.     WHERE rn = 1
  198.  
  199.     UNION ALL
  200.  
  201.     SELECT r.DeviceID, g.[Timestamp],  CASE WHEN DATEDIFF(ss,r.[Timestamp], g.[Timestamp]) <= 5 THEN r.groupID ELSE r.groupID + 1 END, g.rn
  202.     FROM recCTE AS r
  203.     JOIN myCTE AS g
  204.     ON g.rn = r.rn + 1
  205. )
  206. SELECT DeviceID, MIN([Timestamp]) AS [started], MAX([Timestamp]) AS ended
  207. FROM recCTE
  208. GROUP BY DeviceId, groupId
  209. OPTION (MAXRECURSION 0);
  210.        
  211. SELECT DeviceId,
  212.        Timestamp,
  213.        COALESCE((Timestamp - lag(Timestamp) OVER w) > interval '15 min', TRUE)
  214.        as session_begins
  215.        COALESCE((lead(Timestamp) OVER w - Timestamp) > interval '15 min', TRUE)
  216.        as session_ends
  217. FROM YourTable
  218. WINDOW w AS (PARTITION BY DeviceId ORDER BY Timestamp);