将因子乘以具有日期范围的两个表之间的重叠

时间:2013-03-14 15:42:25

标签: sql database oracle intervals oracle9i

我正在使用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中的零或更多重叠,反之亦然。间隔在同一个表格内可靠地不重叠。

对于xdaysproducts之间的每个重叠slowdown,我需要将time_reduction计算为xdays * 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语句?

3 个答案:

答案 0 :(得分: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

答案 1 :(得分: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

答案 2 :(得分:0)

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