Sql 100个逗号分隔的随机计数器位置值构成一个总和,并显示最近60分钟的统计数据

Sql 100个逗号分隔的随机计数器位置值构成一个总和,并显示最近60分钟的统计数据,sql,oracle,pentaho,Sql,Oracle,Pentaho,我试图在pentaho仪表板上显示最近60分钟的统计数据(oracle 11g查询传递给pentaho)。 我的表中有一列(counter_buff),有1000个计数器位置,示例数据如下所示 counter_buff= '0,8,9,3,2,6,....15,62' up to 1000 comma seperated values 我试图根据提供的固定位置从表中获取每个逗号分隔的值,并对它们求和,所以问题是,如果我使用多个位置,查询会变得更大&越慢,查询结果越慢,仪表板上的统计数据就会

我试图在pentaho仪表板上显示最近60分钟的统计数据(oracle 11g查询传递给pentaho)。 我的表中有一列(counter_buff),有1000个计数器位置,示例数据如下所示

counter_buff= '0,8,9,3,2,6,....15,62'  up to 1000 comma seperated values 
我试图根据提供的固定位置从表中获取每个逗号分隔的值,并对它们求和,所以问题是,如果我使用多个位置,查询会变得更大&越慢,查询结果越慢,仪表板上的统计数据就会延迟

我创建了以下示例查询和结果:

查询:

{}中显示的数字是计数器位置({16},{24}..),此位置将由用户定义。同样使用6个union进行查询,如下所示

select * from
((SELECT MIN(to_char(TIMESTAMP,'HH24:MI:SS')) as TS,
         'SELL' as "STATUS",
         SUM((regexp_substr(counter_buff,'(.*?,){16}(.*?),', 1, 1,'', 2)) +
             (regexp_substr(counter_buff,'(.*?,){24}(.*?),', 1, 1,'', 2)) +
             (regexp_substr(counter_buff,'(.*?,){32}(.*?),', 1, 1,'', 2)) ......+
             (regexp_substr(counter_buff,'(.*?,){168}(.*?),', 1, 1,'', 2))) AS  "COUNTS"
    FROM (SELECT * FROM SHOPS
          order by TO_CHAR("TIMESTAMP",'YYYY-MM-DD HH24:MI:SS') desc) "SHOPS"
   where TOY_NAME = 'LION'
     and rownum <=60
   GROUP BY TO_CHAR("TIMESTAMP",'HH24:MI'))
  UNION ALL
 (SELECT MIN(to_char(TIMESTAMP,'HH24:MI:SS')) as TS,
         'RETURNED' as "STATUS",
         SUM((regexp_substr(counter_buff,'(.*?,){17}(.*?),', 1, 1,'', 2)) +
             (regexp_substr(counter_buff,'(.*?,){25}(.*?),', 1, 1,'', 2)) ..... +
             (regexp_substr(counter_buff,'(.*?,){153}(.*?),', 1, 1,'', 2)) +
             (regexp_substr(counter_buff,'(.*?,){161}(.*?),', 1, 1,'', 2)) +
             (regexp_substr(counter_buff,'(.*?,){169}(.*?),', 1, 1,'', 2))) AS "COUNTS"
    FROM (SELECT * FROM SHOPS
          order by TO_CHAR("TIMESTAMP",'YYYY-MM-DD HH24:MI:SS') desc) "SHOPS"
   where TOY_NAME = 'LION'
     and rownum <=60
   GROUP BY TO_CHAR("TIMESTAMP",'HH24:MI')) )
order by TS desc,STATUS desc
我能够实现我想要的输出,但是我想要更快更小的查询选项


我不熟悉oracle query

您应该首先尽可能多地过滤数据,然后完成其余的工作。另外,不需要使用
联合
,您可以在一个分组中执行所有操作,然后仅在需要时取消PIVOT结果。 下面是两个查询,应该很有用。首先,您必须根据需要多次编写
regexp\u substr

/* sample data
with shops(toy_name, time_stamp, counter_buff) as (
    select 'LION', timestamp '2018-07-27 13:15:27', '0,8,9,3,2,6,15,62'    from dual union all
    select 'BEAR', timestamp '2018-07-27 13:44:06', '7,3,9,3,3,6,11,39'    from dual union all
    select 'LION', timestamp '2018-07-27 16:03:09', '7,3,151,44,3,6,11,39' from dual union all
    select 'LION', timestamp '2018-07-27 16:03:49', '7,3,11,4,3,6,11,39'   from dual )
-- end of data */
select to_char(time_stamp, 'hh24:mi') ts, 
       sum(regexp_substr(counter_buff,'(.*?,){2}(.*?),', 1, 1,'', 2) + 
           regexp_substr(counter_buff,'(.*?,){5}(.*?),', 1, 1,'', 2)) sell, 
       sum(regexp_substr(counter_buff,'(.*?,){3}(.*?),', 1, 1,'', 2) + 
           regexp_substr(counter_buff,'(.*?,){6}(.*?),', 1, 1,'', 2)) retu
  from (select time_stamp, counter_buff, row_number() over (order by time_stamp desc) rn 
          from shops where toy_name = 'LION') t
  where rn <= 60
  group by to_char(time_stamp, 'hh24:mi')

在这两个查询中,我假设
sell
处于位置(2,5),
返回的
处于位置(3,6)。还可以尝试对
rownum
执行
row\u number()
,并检查哪个更快。在这两种情况下,数据只命中一次,这将加快计算速度。

使用数据库时,如果您对单独的值不感兴趣,请仅存储逗号分隔的值。如果您对单独的值感兴趣,请分别存储它们。
/* sample data
with shops(toy_name, time_stamp, counter_buff) as (
    select 'LION', timestamp '2018-07-27 13:15:27', '0,8,9,3,2,6,15,62'    from dual union all
    select 'BEAR', timestamp '2018-07-27 13:44:06', '7,3,9,3,3,6,11,39'    from dual union all
    select 'LION', timestamp '2018-07-27 16:03:09', '7,3,151,44,3,6,11,39' from dual union all
    select 'LION', timestamp '2018-07-27 16:03:49', '7,3,11,4,3,6,11,39'   from dual )
-- end of data */
select to_char(time_stamp, 'hh24:mi') ts, 
       sum(regexp_substr(counter_buff,'(.*?,){2}(.*?),', 1, 1,'', 2) + 
           regexp_substr(counter_buff,'(.*?,){5}(.*?),', 1, 1,'', 2)) sell, 
       sum(regexp_substr(counter_buff,'(.*?,){3}(.*?),', 1, 1,'', 2) + 
           regexp_substr(counter_buff,'(.*?,){6}(.*?),', 1, 1,'', 2)) retu
  from (select time_stamp, counter_buff, row_number() over (order by time_stamp desc) rn 
          from shops where toy_name = 'LION') t
  where rn <= 60
  group by to_char(time_stamp, 'hh24:mi')
with 
  /* sample data
  shops(toy_name, time_stamp, counter_buff) as (
    select 'LION', timestamp '2018-07-27 13:15:27', '0,8,9,3,2,6,15,62'    from dual union all
    select 'BEAR', timestamp '2018-07-27 13:44:06', '7,3,9,3,3,6,11,39'    from dual union all
    select 'LION', timestamp '2018-07-27 16:03:09', '7,3,151,44,3,6,11,39' from dual union all
    select 'LION', timestamp '2018-07-27 16:03:49', '7,3,11,4,3,6,11,39'   from dual ),
  */ -- end of sample data
  sell as (select rownum rn, column_value cs from table(sys.odcinumberlist(2, 5)) ),
  retu as (select rownum rn, column_value cr from table(sys.odcinumberlist(3, 6)) )
select *
  from (
    select sum(regexp_substr(counter_buff,'(.*?,){'||cs||'}(.*?),', 1, 1,'', 2)) sell, 
           sum(regexp_substr(counter_buff,'(.*?,){'||cr||'}(.*?),', 1, 1,'', 2)) retu, ts
      from (select to_char(time_stamp, 'HH24:MI') ts, counter_buff 
              from (select * from shops where toy_name = 'LION' order by time_stamp desc) 
              where rownum <= 60)
      cross join sell join retu using (rn) group by ts)
  unpivot (val for status in (sell, retu))