用户接受失败

时间:2018-01-15 09:20:49

标签: sql oracle

 create table Minutes(Minute varchar2(5));
 create table orders(OrderID varchar(54), Orderplaced TIMESTAMP , 
 Ordercompleted TIMESTAMP);
 insert into orders
 VALUES   
 ('#1',TO_TIMESTAMP('2018-01-15 00:12:20', 'YYYY-MM-DD HH24:MI:SS'), 
 TO_TIMESTAMP( '2018-01-15 00:12:42', 'YYYY-MM-DD HH24:MI:SS'));
 insert into orders
 VALUES
 ('#2',TO_TIMESTAMP('2018-01-15 01:15:20', 'YYYY-MM-DD HH24:MI:SS'), 
 TO_TIMESTAMP( '2018-01-15 02:56:20', 'YYYY-MM-DD HH24:MI:SS'));
 insert into orders
 VALUES
 ('#3',TO_TIMESTAMP('2018-01-15 01:20:20', 'YYYY-MM-DD HH24:MI:SS'), 
 TO_TIMESTAMP( '2018-01-15 03:00:20', 'YYYY-MM-DD HH24:MI:SS'));

 insert into Minutes (Minute)

 select to_char(trunc(sysdate) + interval '1' minute * (level - 1), 
 'HH24:MI') as minute
 from dual
 connect by level <= 1440;

 select a.Minute, nvl(count(b.OrderID),0) as orders
 from Minutes a
 left join orders b
 on a.Minute between to_char(cast( b.Orderplaced as date),'hh24:mi:ss')  and 
 to_char(cast( b.Ordercompleted as date),'hh24:mi:ss')
 where
 a.Minute <= (select to_char(cast (sysdate as date),'hh24:mi:ss') from dual)
 group by a.Minute
 order by 1;

处理时间太长,结果也未送达。  它适用于集成测试。请看一次。

2 个答案:

答案 0 :(得分:0)

我运行了你的代码,对那些测试表运行正常。但是,我建议稍作修改。

  • 您不必使用ORDERS表中的CAST值
  • 甚至更糟是CAST SYSDATE AS DATE - SYSDATE是一个函数 无论如何返回DATE数据类型
  • 没有必要从DUAL中选择它 - 你可以使用它&#34;原样&#34;
  • 即使没有任何回复,COUNT也会返回0,所以你可以 省略NVL功能

这是修改后的SELECT语句:

  SELECT a.minute, COUNT (b.orderid) AS orders
    FROM minutes a
         LEFT JOIN orders b
            ON a.minute BETWEEN TO_CHAR (b.orderplaced, 'hh24:mi:ss')
                            AND TO_CHAR (b.ordercompleted, 'hh24:mi:ss')
   WHERE a.minute <= TO_CHAR (SYSDATE, 'hh24:mi:ss')
GROUP BY a.minute
ORDER BY 1;

这对你意味着什么?我不知道。正如我所说,它运作正常。解释计划说它会对MINUTES和ORDERS表执行全表扫描,因此 - 如果这些表中有 zillion 行,它可能会有所不同。

考虑在您使用的列上创建索引;当您从ORDERS表中仅提取时间时,这两个将是基于函数的。

CREATE INDEX i1_min
   ON minutes (minute);

CREATE INDEX i2_plac
   ON orders (TO_CHAR (orderplaced, 'hh24:mi:ss'));

CREATE INDEX i3_compl
   ON orders (TO_CHAR (ordercompleted, 'hh24:mi:ss'));

然后再试一次;希望你能看到一些改进。

答案 1 :(得分:0)

你说你试图获得&#34;特定日期每分钟的订单数量&#34;以及后来澄清应该是当天。您的查询仅查看时间 - 转换为字符串 - 因此它查看订单表中所有记录的同一时段。实际上,您希望将找到的订单限制在您感兴趣的那一天。据推测,您的UAT环境只有比您在IT中创建的更多天的数据。

您只需添加过滤器即可将其限制为今天下达的订单:

select a.Minute, nvl(count(b.OrderID),0) as orders
from Minutes a
left join orders b
on a.Minute between to_char(cast( b.Orderplaced as date),'hh24:mi:ss')  and 
to_char(cast( b.Ordercompleted as date),'hh24:mi:ss')
and b.Orderplaced > trunc(sysdate) -- added this filter
where
a.Minute <= (select to_char(cast (sysdate as date),'hh24:mi:ss') from dual)
group by a.Minute
order by 1;

虽然你不需要任何演员或子查询或nvl(),正如@Littlefoot所提到的那样,所以可以简化一下:

select a.Minute, count(b.OrderID) as orders
from Minutes a
left join orders b
on a.Minute between to_char(b.Orderplaced,'hh24:mi:ss')  and 
to_char(b.Ordercompleted,'hh24:mi:ss')
and b.Orderplaced > trunc(sysdate)
where a.Minute <= to_char(sysdate,'hh24:mi:ss')
group by a.Minute
order by 1;

您仍在进行大量转换并比较字符串而不是日期/时间戳。在CTE而不是永久表中生成特定日期的分钟可能更简单,并且也可以使用这些值进行连接,而无需进行任何进一步的数据转换

with minutes (minute) as (
  select cast(trunc(sysdate) as timestamp) + interval '1' minute * (level - 1)
  from dual
  connect by level <= (sysdate - trunc(sysdate)) * 1440
)
select to_char(m.minute, 'HH24:MI') as minute, count(o.orderid) as orders
from minutes m
left join orders o
on o.orderplaced >= cast(trunc(sysdate) as timestamp)
and o.orderplaced <= m.minute
and (o.ordercompleted is null or o.ordercompleted >= m.minute)
group by m.minute
order by m.minute;

我已经包含了没有ordercompleted日期的行,但如果您想计算这些行,则不清楚。

您也可以加入今天的orderplaced日期,看起来有点奇怪,并进行条件计数:

with minutes (minute) as (
  select cast(trunc(sysdate) as timestamp) + interval '1' minute * (level - 1)
  from dual
  connect by level <= (sysdate - trunc(sysdate)) * 1440
)
select to_char(m.minute, 'HH24:MI') as minute,
  count(case when o.orderplaced <= m.minute
      and (o.ordercompleted is null or o.ordercompleted >= m.minute)
    then o.orderid end) as orders
from minutes m
left join orders o
on o.orderplaced >= cast(trunc(sysdate) as timestamp)
group by m.minute
order by m.minute;

无论哪种方式,这都假定您在orderplaced上有索引。

查看原始查询的执行计划以及这些选项和其他建议,并使用实际数据进行测试,以了解哪种方法可以满足您的实际数据和要求。

要查找其他完整日期的记录,请将sysdate引用更改为timestamp '2018-01-15 00:00:00'之类的日期/时间戳文字或trunc(sysdate-1)之类的相对内容,并包括结尾 - 日期orderplaced;并删除CTE中的结束时间过滤器; e.g:

with minutes (minute) as (
  select cast(trunc(sysdate - 1) as timestamp) + interval '1' minute * (level - 1)
  from dual
  connect by level <= 1440
)
select to_char(m.minute, 'HH24:MI') as minute, count(o.orderid) as orders
from minutes m
left join orders o
on o.orderplaced >= cast(trunc(sysdate - 1) as timestamp)
and o.orderplaced < cast(trunc(sysdate - 1) as timestamp) + interval '1' day
and o.orderplaced <= m.minute
and (o.ordercompleted is null or o.ordercompleted >= m.minute)
group by m.minute
order by m.minute;

with minutes (minute) as (
  select timestamp '2018-01-15 00:00:00' + interval '1' minute * (level - 1)
  from dual
  connect by level <= 1440
)
select to_char(m.minute, 'HH24:MI') as minute, count(o.orderid) as orders
from minutes m
left join orders o
on o.orderplaced >= timestamp '2018-01-15 00:00:00'
and o.orderplaced < timestamp '2018-01-16 00:00:00'
and o.orderplaced <= m.minute
and (o.ordercompleted is null or o.ordercompleted >= m.minute)
group by m.minute
order by m.minute;

如果要包含已放置和完成时间在同一分钟内的行,但仍然希望从放置它们的那一刻开始排除行,那么您需要更多逻辑;也许是这样的:

with minutes (minute) as (
  select timestamp '2018-01-15 00:00:00' + interval '1' minute * (level - 1)
  from dual
  connect by level <= 1440
)
select to_char(m.minute, 'HH24:MI') as minute, count(o.orderid) as orders
from minutes m
left join orders o
on o.orderplaced >= timestamp '2018-01-15 00:00:00'
and o.orderplaced < timestamp '2018-01-16 00:00:00'
and ((trunc(o.ordercompleted, 'MI') > trunc(o.orderplaced, 'MI')
    and o.orderplaced <= m.minute)
  or (trunc(o.ordercompleted, 'MI') = trunc(o.orderplaced, 'MI')
    and o.orderplaced < m.minute + interval '1' minute))
and (o.ordercompleted is null or o.ordercompleted >= m.minute)
group by m.minute
order by m.minute;

如果您需要进一步改进,您需要修改适合的条款,这可能需要一些实验。