动态时间间隔差距

时间:2018-02-05 14:54:37

标签: sql sql-server function

请看一下这段代码并告诉我为什么它没有产生预期的结果,结果应该是找到15分钟的差距(动态)并从找到差距的点开始

这是代码(它应该返回5条记录和15分钟的间隙)

drop table if exists example

CREATE TABLE example(
       [ID] [varchar](9) NULL,
       [DTTM] [datetime] NULL,
       [RN] Int null,
       [COUNTFLAG] int
) ON [PRIMARY] 

Insert into [example] (ID,DTTM) values 
('123456789','2017-10-05 08:00:00.000'), -- Expected Result
('123456789','2017-10-05 08:05:00.000'), 
('123456789','2017-10-05 08:07:00.000'),
('123456789','2017-10-05 08:15:00.000'), -- Expected Result
('123456789','2017-10-05 08:25:00.000'),
('123456789','2017-10-05 10:12:00.000') , -- Expected Result
('123456789','2017-10-05 10:26:00.000'),
('123456789','2017-10-05 10:32:00.000'),  -- Expected Result
('123456789','2017-10-05 10:33:00.000'),
('123456789','2017-10-05 10:34:00.000'),
('123456789','2017-10-05 10:35:00.000'),
('123456789','2017-10-05 10:36:00.000'),
('123456789','2017-10-05 10:37:00.000'),
('123456789','2017-10-05 10:38:00.000'),
('123456789','2017-10-05 10:39:00.000'),
('123456789','2017-10-05 10:40:00.000'),
('123456789','2017-10-05 10:41:00.000'),
('123456789','2017-10-05 10:42:00.000'),
('123456789','2017-10-05 10:43:00.000'),
('123456789','2017-10-05 10:44:00.000'),
('123456789','2017-10-05 10:45:00.000'),
('123456789','2017-10-05 10:46:00.000'),
('123456789','2017-10-05 10:47:00.000'),  -- Expected Result
('123456789','2017-10-05 10:48:00.000')



WITH Step1 AS (
 select ID, DTTM ,  NextVal
 FROM example A 
 OUTER APPLY (
  SELECT TOP(1) DTTM AS NextVal 
  FROM example AS B 
  WHERE dateadd(minute,15,(A.DTTM)) <= B.DTTM
   AND A.ID = B.ID
  ORDER BY DTTM) AS B
)
SELECT  A.ID, min(a.dttm) As MinDate, min(B.DTTM) AS MaxDate
FROM Step1 AS A
JOIN Step1 AS B ON A.NextVal = B.DTTM AND A.ID = B.ID
group by A.ID, b.NextVal
ORDER BY min(a.dttm);

1 个答案:

答案 0 :(得分:2)

从您的解释中不清楚您是否可以拥有多个ID,但是因为您在身份证上使用GROUP BY我相信您可以拥有。然后像这样的一些递归CTE将完成这项工作:

WITH times AS (
    SELECT e.ID, MIN(e.DTTM) AS DTTM
    FROM example e
    GROUP BY e.ID

    UNION ALL

    SELECT r.ID, r.DTTM
    FROM (
        SELECT e.ID, e.DTTM,
            ROW_NUMBER() OVER (PARTITION BY e.ID ORDER BY e.DTTM) AS rn
        FROM example e
        INNER JOIN times t
            ON e.ID = t.ID AND e.DTTM >= DATEADD(mi, 15, t.DTTM)
    ) r
    WHERE r.rn = 1
)

SELECT *
FROM times
ORDER BY ID, DTTM
;

查询首次抓取每个ID(第一个SELECT,在UNION ALL之前)然后递归,找到每个ID至少15分钟的下一行。

期望在(ID,DTTM)上具有索引。您是否有一个大型数据表来尝试它并检查它是否产生正确的结果并且表现良好?顶部带有GROUP BY的SELECT将导致扫描,但也许可以接受。如果不告诉我们。