SQL查询比较时差

时间:2017-03-31 07:05:03

标签: sql-server-2012

我使用下面的代码查询并显示输出。现在,我想查询如下所述。我该怎么办?

  

查找代码2,检查代码1是否在同一ItemID中的代码2之后。如果是,请比较时差。如果时差小于10秒,则显示两个比较行。

    SELECT [Date]
      ,[Code]
      ,[ItemId]
      ,[ItemName]
  FROM [dbo].[Log] as t
join Item as d
on t.ItemId = d.Id
  where ([Code] = 2 or [Code] = 1) and ([ItemId] > 97 and [ItemId] < 100)
  order by [ItemId], [Date]

以上查询的输出

         Date           Code  ItemName  ItemID  
2017-01-06 11:00:49.000  2       B      98
2017-01-06 11:00:49.000  1       A      98
2017-01-06 11:00:55.000  2       B      98
2017-01-06 12:01:56.000  1       A      98
2017-01-06 12:02:37.000  2       B      98
2017-01-06 12:03:49.000  1       A      98
2017-01-06 12:05:44.000  2       B      98
2017-01-06 20:24:32.000  1       A      98
2017-01-06 20:24:55.000  2       B      98
2017-03-14 16:37:42.000  2       B      99
2017-03-14 17:40:24.000  1       A      99
2017-03-14 17:40:25.000  2       B      99
2017-03-14 21:28:46.000  1       A      99
2017-03-15 08:03:07.000  2       B      99
2017-03-15 10:43:00.000  1       A      99
2017-03-15 12:01:17.000  2       B      99
2017-03-15 14:18:19.000  2       B      99

预期结果

         Date           Code  ItemName  ItemID  
2017-01-06 11:00:49.000  2       B      98
2017-01-06 11:00:49.000  1       A      98

1 个答案:

答案 0 :(得分:1)

create table results ([Date] datetime, Code int, ItemName char(1), ItemID int);
insert into results values
('2017-01-06 11:00:49',  2,       'B',      98),
('2017-01-06 11:00:49',  1,       'A',      98),
('2017-01-06 11:00:55',  2,       'B',      98),
('2017-01-06 12:01:56',  1,       'A',      98),
('2017-01-06 12:01:58',  1,       'A',      98),
('2017-01-06 12:02:37',  2,       'B',      98),
('2017-01-06 12:03:49',  1,       'A',      98),
('2017-01-06 12:05:44',  2,       'B',      98),
('2017-01-06 20:24:32',  1,       'A',      98),
('2017-01-06 20:24:55',  2,       'B',      98),
('2017-03-07 00:02:27',  1,       'A',      91),
('2017-03-07 00:02:27',  1,       'A',      58),
('2017-03-14 16:37:42',  2,       'B',      99),
('2017-03-14 17:40:24',  1,       'A',      99),
('2017-03-14 17:40:38',  2,       'B',      99),
('2017-03-14 21:28:46',  1,       'A',      99),
('2017-03-15 08:03:07',  2,       'B',      99),
('2017-03-15 10:43:00',  1,       'A',      99),
('2017-03-15 12:01:17',  2,       'B',      99),
('2017-03-15 14:18:19',  1,       'A',      99);
--= set a reset point when ItemId changes, or there is no correlative (2,1) couples
--= keep in mind this solution assumes that first Code must be 2
--
WITH SetReset AS
(
    SELECT [Date], Code, ItemName, ItemId,
           CASE WHEN LAG([ItemId]) OVER (PARTITION BY ItemId ORDER BY [Date]) IS NULL
                     OR ([Code] = 2)
                     OR ([Code] = COALESCE(LAG([Code]) OVER (PARTITION BY ItemId ORDER BY [Date]), [Code]))
                THEN 1 END is_reset
    FROM   results

)
--
--= set groups according to reset points
--
, SetGroup AS
   (
        SELECT [Date], Code, ItemName, ItemId,
               COUNT(is_reset) OVER (ORDER BY [ItemId], [Date]) grp
        FROM   SetReset
    )
    --
    --= calcs diff date for each group 
    , CalcSeconds AS
    (
        SELECT [Date], Code, ItemName, ItemId,
               DATEDIFF(SECOND, MIN([Date]) OVER (PARTITION BY grp), MAX([Date]) OVER (PARTITION BY grp)) dif_sec,
               COUNT(*) OVER (PARTITION BY grp) num_items
        FROM   SetGroup
    )
    --
    --= selects those rows with 2 items by group and date diff less than 10 sec
    SELECT [Date], Code, ItemName, ItemId
    FROM   CalcSeconds
    WHERE  dif_sec < 10 
    AND    num_items = 2
;
GO
Date                | Code | ItemName | ItemId
:------------------ | ---: | :------- | -----:
06/01/2017 11:00:49 |    2 | B        |     98
06/01/2017 11:00:49 |    1 | A        |     98

Warning: Null value is eliminated by an aggregate or other SET operation.

dbfiddle here