如何查找表中行之间的平均时差?

时间:2009-05-18 09:20:18

标签: sql mysql

我有一个存储一些时间戳的mysql数据库。我们假设表中的所有内容都是ID和时间戳。时间戳可能重复。

我想找到不重复的连续行之间的平均时差(按时间)。有没有办法在SQL中执行此操作?

4 个答案:

答案 0 :(得分:29)

如果您的表格为t,并且您的时间戳列为ts,并且您希望在几秒钟内得到答案:

SELECT TIMESTAMPDIFF(SECOND, MIN(ts), MAX(ts) ) 
       /
       (COUNT(DISTINCT(ts)) -1) 
FROM t

对于大型桌子来说这会更快,因为它没有n平方JOIN

这使用了一个可爱的数学技巧来帮助解决这个问题。暂时忽略重复的问题。连续行之间的平均时间差是第一个时间戳和最后一个时间戳之间的差值除以行数-1。

证明:连续行之间的平均距离是连续行之间的距离之和除以连续行数。但是连续行之间差异的总和只是第一行和最后一行之间的距离(假设它们按时间戳排序)。并且连续行数是总行数-1。

然后我们只是将时间戳区分开来。

答案 1 :(得分:2)

ID是否连续?

你可以做点什么,

SELECT 
      a.ID
      , b.ID
      , a.Timestamp 
      , b.Timestamp 
      , b.timestamp - a.timestamp as Difference
FROM
     MyTable a
     JOIN MyTable b
          ON a.ID = b.ID + 1 AND a.Timestamp <> b.Timestamp

这将为您提供每个连续行对的时间差列表...

然后你可以把它包装成一个AVG分组......

答案 2 :(得分:1)

这是一种方式:

select avg(timestampdiff(MINUTE,prev.datecol,cur.datecol))
from table cur
inner join table prev 
    on cur.id = prev.id + 1 
    and cur.datecol <> prev.datecol

timestampdiff功能允许您在天,月,秒等之间进行选择。

如果id不是连续的,您可以通过添加中间没有其他行的规则来选择上一行:

select avg(timestampdiff(MINUTE,prev.datecol,cur.datecol))
from table cur
inner join table prev 
    on prev.datecol < cur.datecol
    and not exists (
        select * 
        from table inbetween 
        where prev.datecol < inbetween.datecol
        and inbetween.datecol < cur.datecol)
    )

答案 3 :(得分:0)

此讨论中的内容适用于SQL Server。

使用的基本列为: cmis_load_date:与每个记录关联的日期/时间戳。 extract_file:从中加载记录的文件的完整路径。

评论: 每个文件中可以有很多记录。记录必须根据extract_file列上加载的文件进行分组。一个文件与另一个文件之间的间隔可能为几天。在任何列中都没有可靠的顺序值,因此将按每个文件组中的最小加载日期对分组的行进行排序,然后将ROW_NUMBER()函数用作临时顺序值。

SELECT 
AVG(DATEDIFF(day,  t2.MinCMISLoadDate, t1.MinCMISLoadDate)) as ElapsedAvg
FROM
(
SELECT 
ROW_NUMBER() OVER (ORDER BY MIN(cmis_load_date)) as RowNumber,  
MIN(cmis_load_date) as MinCMISLoadDate,
CASE WHEN NOT CHARINDEX('\', extract_file) > 0 THEN '' ELSE RIGHT(extract_file, CHARINDEX('\', REVERSE(extract_file)) - 1) END as ExtractFile
FROM
TrafTabRecordsHistory 
WHERE 
court_id = 17
and 
cmis_load_date >= '2019-09-01'
GROUP BY 
CASE WHEN NOT CHARINDEX('\', extract_file) > 0 THEN '' ELSE RIGHT(extract_file, CHARINDEX('\', REVERSE(extract_file)) - 1) END
) t1
LEFT JOIN 
(
SELECT 
ROW_NUMBER() OVER (ORDER BY MIN(cmis_load_date)) as RowNumber,  
MIN(cmis_load_date) as MinCMISLoadDate,
CASE WHEN NOT CHARINDEX('\', extract_file) > 0 THEN '' ELSE RIGHT(extract_file, CHARINDEX('\', REVERSE(extract_file)) - 1) END as ExtractFile
FROM
TrafTabRecordsHistory 
WHERE 
court_id = 17
and 
cmis_load_date >= '2019-09-01'
GROUP BY 
CASE WHEN NOT CHARINDEX('\', extract_file) > 0 THEN '' ELSE RIGHT(extract_file, CHARINDEX('\', REVERSE(extract_file)) - 1) END
) t2 on t2.RowNumber + 1 = t1.RowNumber
相关问题