Oracle 按时间段对合格行进行分组,包括零计数

Posted

技术标签:

【中文标题】Oracle 按时间段对合格行进行分组,包括零计数【英文标题】:Oracle group qualifying rows by time period including zero counts 【发布时间】:2014-05-12 04:38:28 【问题描述】:

假设我有一个 Oracle 10g 表,它记录了我系统上的所有响应时间。如何按日期获取计数缓慢的交易,包括没有交易缓慢的日期的零计数?

举个例子

create table response_times (system_datetime timestamp, server_name varchar2(3), response_time number(9));

insert into response_times (system_datetime, server_name, response_time)
values (to_date('01/05/2014 12:30', 'DD/MM/YYYY HH24:MI'), 'D01', 500);

insert into response_times (system_datetime, server_name, response_time)
values (to_date('01/05/2014 13:45', 'DD/MM/YYYY HH24:MI'), 'D02', 700);

insert into response_times (system_datetime, server_name, response_time)
values (to_date('01/05/2014 14:01', 'DD/MM/YYYY HH24:MI'), 'D01', 2500);

insert into response_times (system_datetime, server_name, response_time)
values (to_date('02/05/2014 07:45', 'DD/MM/YYYY HH24:MI'), 'D02', 2500);

insert into response_times (system_datetime, server_name, response_time)
values (to_date('02/05/2014 08:30', 'DD/MM/YYYY HH24:MI'), 'D02', 500);

我想查看响应时间超过 2000 毫秒的事务数,如下所示:

TRUNC(system_datetime)  D01    D02
=====================   ===    ===
2014/05/01              1      0
2014/05/02              0      1
2014/05/03              0      0

有没有办法在单个 sql 语句中检索它?在实践中会有数百万行,(希望)每天只有几个慢事务,并且在某些日子根本不会有慢事务。

现在我知道我可以编写一个简短的 PL/SQL 过程来使用候选日期的临时表来获取它,并使用一个循环来为每个时间段发出 select count(*) 以获得计数值,但是我希望有一种更优雅的方式......

【问题讨论】:

【参考方案1】:

其中的关键是生成日期。这是一种方法:

with n as (
      select level as lvl from dual
      connect by level < 5
     ),
     dates as (
      select (to_date('2014-05-01', 'YYYY-MM-DD') + lvl - 1) as d
      from n
     )
select dates.d, coalesce(r.D01, 0) as D01, coalesce(r.D02, 0) as D02
from dates left outer join
     (select TRUNC(system_datetime) as dt,
             sum(case when server_name = 'D01' then 1 else 0 end) as D01,
             sum(case when server_name = 'D02' then 1 else 0 end) as D02
      from response_times
      group by TRUNC(system_datetime) 
     ) r
     on dates.d = r.dt;

一旦有了日期,剩下的就是left outer join

【讨论】:

太棒了,我可以用这个。非常感谢。

以上是关于Oracle 按时间段对合格行进行分组,包括零计数的主要内容,如果未能解决你的问题,请参考以下文章

Oracle SQL 查询计数组按时间戳子串

对超过百万行进行排序的分组

MySQL:按连续天分组并计数组

如何在 Oracle SQL 上进行查询以获取时间间隔,按特定字段分组

在 jQuery 中按数据属性对 HTML 元素进行分组和计数

MySQL按天计数和分组