我有一个问题很难解决,我想你可以帮助。我有一个表中有数百万条记录,其中精确的组每10分钟,根据注册表值,例如:
记录“01| 2011/01/03 19:18:00.300”它需要对记录进行计数的时间是19:18:00.300到19:28:00.299。通过此过程,它将对记录01,02,03进行分组。
记录“04| 2011/01/03 19:29:54.289”它需要对记录进行计数的时间是19:29:54.289到19:39:54.288。在此过程中,它将只对记录04进行分组。
记录“05| 2011/01/04 14:43:43.067”,他需要对记录进行计数的时间是14:43:43.067到14:43:53.066。通过此过程,它将对记录05,06,07进行分组。
记录“08| 2011/01/04 14:57:55.608;”它需要对记录进行计数的时间是14:57:55.608到15:07:55.607。通过此过程,它将对记录08,09,10,11,12,13,14,15进行分组。
输入数据:
ID TS
01 2011/01/03 19:18:00.300
02 2011/01/03 19:18:00.503
03 2011/01/03 19:20:26.335
04 2011/01/03 19:29:54.289
05 2011/01/04 14:43:43.067
06 2011/01/04 14:50:10.727
07 2011/01/04 14:52:26.827
08 2011/01/04 14:57:55.608
09 2011/01/04 14:57:55.718
10 2011/01/04 14:59:13.603
11 2011/01/04 15:00:34.260
12 2011/01/04 15:02:55.687
13 2011/01/04 15:04:51.917
14 2011/01/04 15:06:24.760
15 2011/01/04 15:07:15.378
字符串
输出数据:
ID TS Count
01 2011/01/03 19:18:00.300 3
02 2011/01/03 19:29:54.289 1
03 2011/01/04 14:43:43.067 3
04 2011/01/04 14:57:55.608 8
型
有没有人有解决这个问题的办法?已经,感谢关注。
3条答案
按热度按时间kpbwa7wx1#
我有一个有数百万条记录的表,其中每10分钟精确分组
**t1; dr:**对于不耐烦的人,请看答案中的最后一个查询,这是真实的解决方案,其他的都是一步一步的如何到达那里。另外,所有的查询+模式都可以在SQLFiddle上找到,对于那些想玩的人来说。
在我看来,解决这个问题的最好方法是将每个时间戳截断为10分钟的开始,例如,让我们尝试进行以下转换(
original -> 10 minutes truncated
):字符串
如果有人想尝试以下查询,可以将模式创建为:
型
因此,为了做到这一点,我们需要理解
date_trunc
和date_part
函数(后者可以由标准EXTRACT
调用)和interval
data type。让我们一步一步地构建解决方案,最终的想法是有这样的东西(现在是伪代码):型
现在,如果问题是“按分钟聚合”,那么我们可以简单地将时间戳截断为分钟,这意味着将秒和微秒归零,这正是
date_trunc('minute', ...)
所做的,所以:型
工作,但这不是你想要的,
date_trun
的下一个功能是'hour'
,这已经失去了我们需要的信息,所以我们需要在'minute'
和'hour'
之间的东西。让我们通过一些例子来看看上面的查询是如何工作的:型
它返回:
型
如果你看到
2011-01-03 19:18:00-02
,现在我们只需要减去8分钟,我们可以:1.
EXTRACT(MINUTE FROM tscol)
将返回18
1.因为我们想截短10分钟,让我们取
18 and 10
的模,所以**18 % 10
给予我们8
**1.现在,我们有
8
分钟,我们要减去,但作为一个整数,从timestamp[tz]
减去,我们需要interval
,因为整数代表分钟,我们可以这样做:8 * interval '1 minute'
,这将给予我们**00:08:00
**在最后一个查询中得到上面的3个步骤,我们有(我将显示每一列以更好地理解):
型
它返回:
型
现在,最后一列是我们想要的解决方案,时间戳被截断为10分钟组,现在我们可以简单地聚合并获得我们的最终解决方案:
型
它返回:
型
这就是你给出的确切输出,但我相信这是你实际期望的,如果不是,那只是一个小调整的问题。
nnt7mjpx2#
递归查询检测间隔的开始和停止时间; count(*)标量子查询计算每个间隔内的原始记录数。
字符串
v2g6jxz63#
动态界限(提问)
每个组的边界都依赖于前一个组,所以它不适合于基于集合的解,我们必须遍历表来确定边界。
字符串
fiddle
请确保时间戳列上有一个普通索引。
基本上是模拟索引跳过扫描的另一个应用。请参阅:
wildplasser提供了一个可行的解决方案,但它更简单、更快。
固定的10分钟网格
就简单多了。
型
fiddle的
不需要索引。导致单个顺序扫描,因此速度更快。
date_bin()
需要Posterre 14或更新版本。请参阅:MatheusOl为旧的Posterre版本提供了一个有效的解决方案。