如何选择第一次输入,然后仅间隔大于 5 分钟

Posted

技术标签:

【中文标题】如何选择第一次输入,然后仅间隔大于 5 分钟【英文标题】:How to Select the first time entry, then only times greater than 5 minutes apart 【发布时间】:2019-05-22 19:52:15 【问题描述】:
 CREATE TABLE import_time
    ( date datetime NUll,
    time datetime Null,
    Employeeid nvarchar(25) Null)

 INSERT INTO import_time (date, time, Employeeid) 
 Values ('2019-05-22 00:00:00.000', '1900-01-01 12:50:12.000', '1234') 
  , ('2019-05-22 00:00:00.000', '1900-01-01 12:55:00.000', '1234') 
  , ('2019-05-22 00:00:00.000', '1900-01-01 13:25:12.000', '1234')
  , ('2019-05-22 00:00:00.000', '1900-01-01 13:50:12.000', '1234')

如何只选择第一次输入的时间,然后选择相隔大于 5 分钟的时间? 查询应返回 12:50、13:25 和 13:50 而不是 12:55 条目

【问题讨论】:

为什么将日期存储为datetime 并包含一个没有日期组件的时间列?这很奇怪。如果你有12:57:00,会不会被选中? 我从中收集数据的程序将时间存储为日期时间数据类型。我只是在模拟我在更大的数据库中看到的内容。 -问候 B @GordonLinoff 我在 sql 2000 和在日期和时间数据类型出现之前的几天里看到了许多类似的数据库。不是说这是一个好计划,只是我很久以前看到的。 最好使用标签来指定您正在使用的软件版本。这样您可以获得更好的答案 【参考方案1】:

首先将前一行的日期和时间添加到每一行。 您可以使用 LED 来做到这一点。希望您拥有 SQL Server 2012 及更高版本

您还应该注意午夜前后的时间,因为对于这些条目,如果您只比较时间可能会出错。

;with ct as (
    select [date], [time], Employeeid
    , prev_date = lag([date]) over (partition by Employeeid order by [date], [time])
    , prev_time = lag([time]) over (partition by Employeeid order by [date], [time])
from #time
)
select [date], [time], Employeeid
from ct
where prev_date is null or prev_time is null -- this gives you the first entry
      or datediff(minute, prev_date + prev_time, date + time) > 5

结果:

【讨论】:

【参考方案2】:

您可以使用NOT EXISTS 来检查当前时间过去五分钟内是否没有其他行的时间更短或相等,我们使用dateadd() 得到。

要确定某行是否不是当前行,您需要一个键。在您的帖子中没有一个的情况下,我使用了未记录的 %%physloc%% 伪列作为代理。但无证意味着如有更改,恕不另行通知,因此您想替换它。

要修复拆分日期时间,您可以使用+

为方便起见,我使用 CTE 将原始表格准备为更可用的表格。

WITH
cte
AS
(
SELECT date,
       time,
       employeeid,
       date + time datetime,
       %%physloc%% physloc
       FROM import_time
)
SELECT c1.date,
       c1.time,
       c1.employeeid
       FROM cte c1
       WHERE NOT EXISTS (SELECT *
                                FROM cte c2
                                WHERE c2.employeeid = c1.employeeid
                                      AND c2.physloc <> c1.physloc
                                      AND c2.datetime <= c1.datetime
                                      AND c2.datetime > dateadd(minute, -5, c1.datetime));

db<>fiddle

【讨论】:

【参考方案3】:

试试这个-

DECLARE @import_time TABLE
( 
    date datetime NUll,
    time datetime Null,
    Employeeid nvarchar(25) Null
)

INSERT INTO @import_time (date, time, Employeeid) 
Values 
    ('2019-05-22 00:00:00.000', '1900-01-01 12:50:12.000', '1234') , 
    ('2019-05-22 00:00:00.000', '1900-01-01 12:55:00.000', '1234') , 
    ('2019-05-22 00:00:00.000', '1900-01-01 13:25:12.000', '1234'), 
    ('2019-05-22 00:00:00.000', '1900-01-01 13:50:12.000', '1234')

SELECT 
CONVERT(VARCHAR(5),B.time ,108) 
FROM
(
    SELECT Employeeid,MIN ([time]) EnrtyTime
    FROM @import_time
    GROUP BY Employeeid
) A
INNER JOIN @import_time B 
    ON A.Employeeid = B.Employeeid
    AND 
    (
        A.EnrtyTime = B.time
        OR
        B.time >= DATEADD(MINUTE,5,A.EnrtyTime)
    )

【讨论】:

以上是关于如何选择第一次输入,然后仅间隔大于 5 分钟的主要内容,如果未能解决你的问题,请参考以下文章

如何选择行的第一个和最后一个值 之间间隔为5分钟

Mysql如何以10分钟间隔选择计数聚合结果

ASP.NET如何判断某个页面已经在浏览器打开

如何使一个批处理命令每间隔一段时间(比如5分钟)运行一次?

怎么让windows计划任务每隔几分钟运行一次?

什么是 SQL 查询以 5 分钟间隔选择数据和数据条目的 AVG