如何随时间动态压缩/聚合/分组包含事件的表。 我有一张表,其中包含值和发生时间。
这样的事情:
value_col time_col
3 | 2011-02-16 22:21:05.250
2 | 2011-02-16 21:21:06.170
15 | 2011-02-16 21:21:05.250
我需要从第一行(最新事件)开始按给定时间跨度(例如每小时)汇总值。所以在这个例子中,我希望最终有两行用于每小时聚合。
5
15
因此,如果有新值:
value_col time_col
6 | 2011-02-16 23:21:05.247
3 | 2011-02-16 22:21:05.250
2 | 2011-02-16 21:21:06.170
15 | 2011-02-16 21:21:05.250
如果我再次运行该查询,我想最终得到:
9
17
更改查询中的时间范围应该很容易。例如压缩过去30秒,过去6小时,过去24小时等等。我怎么能在oracle和MS SQL中做到这一点?
答案 0 :(得分:1)
感谢之前的回答,我了解了如何满足所有要求。
对于每条记录,我计算与最新记录的时差,以毫秒为单位(或秒,具体取决于分辨率)。然后,我模拟了我目前感兴趣的时间跨度(例如3600秒= 1小时)。 然后我将该值添加到同一记录的time_col并将其添加到该组。
创建表格:
CREATE TABLE [dbo].[test_table](
[value_col] [int] NOT NULL,
[time_col] [datetime] NOT NULL
) ON [PRIMARY]
GO
INSERT [dbo].[test_table] ([value_col], [time_col]) VALUES (3, CAST(0x00009E8C01705737 AS DateTime))
INSERT [dbo].[test_table] ([value_col], [time_col]) VALUES (2, CAST(0x00009E8C015FDD8B AS DateTime))
INSERT [dbo].[test_table] ([value_col], [time_col]) VALUES (15, CAST(0x00009E8C015FDC77 AS DateTime))
INSERT [dbo].[test_table] ([value_col], [time_col]) VALUES (6, CAST(0x00009E8C0180D1F6 AS DateTime))
SQL解决方案:
SELECT SUM(value_col) AS s_val, aggregation_time FROM
(SELECT value_col, time_col,
DATEADD(millisecond,DATEDIFF(millisecond,time_col,(SELECT MAX(time_col)
FROM test_table)) % (3600 * 1000), time_col) AS aggregation_time
FROM test_table)
GROUP BY aggregation_time
ORDER BY aggregation_time DESC
Oracle解决方案:
SELECT SUM(value_col) as s_val, aggregation_time FROM
(SELECT value_col, time_col +
(MOD(ROUND(((CAST((SELECT MAX(time_col) FROM test_table) AS DATE ) -
CAST(time_col AS DATE ))*86400),0),3600))/86400 as aggregation_time
FROM test_table l)
GROUP BY aggregation_time
ORDER BY aggregation_time DESC
如果我想在过去2小时内聚合,我只需将3600更改为7200秒。
结果是:
9 2011-02-16 23:21:05.247
17 2011-02-16 22:21:05.247
答案 1 :(得分:0)
a b
3 | 2011-02-16 23:21:05.250
2 | 2011-02-16 22:21:05.267
15 | 2011-02-16 22:21:05.155
with tmp as (
select a, to_char(b, 'YYYYMMDDHH24') h from tab
)
select sum(a), h from tmp group by h
/
答案 2 :(得分:0)
以下是如何按小时汇总的示例:
SELECT TO_CHAR(TRUNC(a.created, 'HH24'), 'DD.MM.YYYY HH24:MI'), COUNT(*)
FROM all_objects a
GROUP BY TRUNC(a.created, 'HH24');
这为您提供了每小时按其创建时间汇总的all_objects
对象数。关键是TRUNC(column, 'HH24')
,每小时汇总一次数据。
在你的情况下,像这样:
create table t (i int, d date);
insert into t values (3, to_date('2011-02-16 22:21:05', 'YYYY-MM-DD HH24:MI:SS'));
insert into t values (2, to_date('2011-02-16 21:21:05', 'YYYY-MM-DD HH24:MI:SS'));
insert into t values (15, to_date('2011-02-16 21:21:05', 'YYYY-MM-DD HH24:MI:SS'));
commit;
select sum(i), TO_CHAR(TRUNC(t.d, 'HH24'), 'DD.MM.YYYY HH24:MI') from t group by TRUNC(t.d, 'HH24');
答案 3 :(得分:0)
对于SQLServer,您将拥有类似
的内容SELECT DATEDIFF(hour,b.date_time_col,a.dt), SUM(b.id)
FROM (SELECT MAX(date_time_col) as dt FROM table1)a,
table1 b
GROUP BY DATEDIFF(hour,b.date_time_col,a.dt)
Oracle没有DATE_DIFF
,相当于TRUNC(24*(a.dt-b.date_time_col))
答案 4 :(得分:0)
这是一个Oracle变体,只使用一个表访问。
SQL> create table t (value,mydate)
2 as
3 select 3, to_timestamp('2011-02-16 22:21:05.250','yyyy-mm-dd hh24:mi:ss.ff3') from dual union all
4 select 2, to_timestamp('2011-02-16 21:21:05.267','yyyy-mm-dd hh24:mi:ss.ff3') from dual union all
5 select 15, to_timestamp('2011-02-16 21:21:05.155','yyyy-mm-dd hh24:mi:ss.ff3') from dual
6 /
Table created.
下一个查询按小时差异分组,从最近的时间戳开始计算,这似乎是您想要的:
SQL> select sum(value)
2 from ( select extract(hour from (max(mydate) over () - mydate)) difference_in_hours
3 , value
4 from t
5 )
6 group by difference_in_hours
7 order by difference_in_hours
8 /
SUM(VALUE)
----------
5
15
2 rows selected.
但显然你的例子不准确,因为当我从你的例子中添加第四行时,15值距离最近的时间戳超过两个小时,这导致了一个额外的组:
SQL> insert into t values (6,to_timestamp('2011-02-16 23:21:05.249','yyyy-mm-dd hh24:mi:ss.ff3'))
2 /
1 row created.
SQL> select sum(value)
2 from ( select extract(hour from (max(mydate) over () - mydate)) difference_in_hours
3 , value
4 from t
5 )
6 group by difference_in_hours
7 order by difference_in_hours
8 /
SUM(VALUE)
----------
9
2
15
3 rows selected.
所以我误解了你的要求,或者你的例子中有错误吗?
的问候,
罗布。