2013-03-14 40 views
0

我使用Oracle 9i和有两个表以重叠的间隔:乘以与日期两个表之间的重叠的因子范围

CREATE TABLE slowdown (startdate DATE, enddate DATE, factor NUMBER); 
CREATE TABLE products (prod VARCHAR2(10 BYTE) NOT NULL, STARTDATE DATE, ENDDATE DATE); -- In my usage this table is actually the result of a query and has many more rows 

INSERT INTO slowdown(startdate, enddate, factor) VALUES (TO_DATE('09-SEP-2012 00:00:00', 'DD-MON-YYYY HH24:MI:SS'), TO_DATE('28-SEP-2012 00:00:00', 'DD-MON-YYYY HH24:MI:SS'), .70); 
INSERT INTO slowdown(startdate, enddate, factor) VALUES (TO_DATE('23-MAR-2013 07:00:00', 'DD-MON-YYYY HH24:MI:SS'), TO_DATE('28-MAR-2013 19:00:00', 'DD-MON-YYYY HH24:MI:SS'), 0); 
INSERT INTO slowdown(startdate, enddate, factor) VALUES (TO_DATE('28-MAR-2013 07:00:00', 'DD-MON-YYYY HH24:MI:SS'), TO_DATE('29-MAR-2013 07:00:00', 'DD-MON-YYYY HH24:MI:SS'), .25); 

INSERT INTO products(prod, startdate, enddate) VALUES ('LOT001', TO_DATE('01-FEB-2012 13:30:00', 'DD-MON-YYYY HH24:MI:SS'), TO_DATE('05-FEB-2012 01:00:00', 'DD-MON-YYYY HH24:MI:SS')); 
INSERT INTO products(prod, startdate, enddate) VALUES ('LOT001', TO_DATE('26-SEP-2012 00:00:00', 'DD-MON-YYYY HH24:MI:SS'), TO_DATE('30-SEP-2012 00:00:00', 'DD-MON-YYYY HH24:MI:SS')); 
INSERT INTO products(prod, startdate, enddate) VALUES ('LOT123', TO_DATE('20-MAR-2013 11:13:45', 'DD-MON-YYYY HH24:MI:SS'), TO_DATE('28-MAR-2013 19:00:00', 'DD-MON-YYYY HH24:MI:SS')); 

正如可以看到,在products的间隔可以与零个或多个重叠在slowdown或反之亦然。间隔可靠地在同一个表内不重叠。

对于每个重叠并且slowdownxdays之间products,我需要计算time_reductionxdays * factor作为。

prod  product_startdate product_enddate  xdays fctr time_reduction 
LOT001 01-FEB-2012 13:30 05-FEB-2012 01:00 0  NULL 0  
LOT001 26-SEP-2012 00:00 30-SEP-2012 00:00 2  0.7 1.4 
LOT123 20-MAR-2012 11:13 28-MAR-2012 19:00 0.5  0.25 0.125 

是否有可以产生此结果的SQL语句?

回答

2
select 
    p.prod, 
    p.startdate as product_startdate, 
    p.enddate as product_enddate, 
    nvl(least(p.enddate, s.enddate) - greatest(p.startdate, s.startdate), 0) as xdays, 
    s.factor as fctr, 
    nvl(s.factor, 0) * nvl(least(p.enddate, s.enddate) - greatest(p.startdate, s.startdate), 0) 
     as time_reduction 
from 
    products p 
    left join slowdown s 
     on least(p.enddate, s.enddate) - greatest(p.startdate, s.startdate) > 0 

fiddle

+0

多么优雅,简单的解决方案。我在脑海中开始了一个递归查询,希望更简单一些。 – 2013-03-15 18:52:29

0

我会为每次计算编写PL/SQL函数,并将它们调用到我的select中以获得所需的结果。可能有一种方法可以在SQL中执行此操作,但会变得有点难看。

1

,你可以这样做:

select prod, startdate, enddate, factor, xdays, 
     xdays * nvl(factor, 1) time_reduction 
    from (select p.*, s.factor, 
       case 
       when s.startdate is null 
       then 
        0 
       else 
        least(p.enddate, s.enddate) - greatest(s.startdate, p.startdate) 
       end xdays 
      from products p, slowdown s 
     where s.startdate(+) <= p.enddate 
      and s.enddate(+) >= p.startdate); 

小提琴:http://sqlfiddle.com/#!4/6983b/1

相关问题