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'));

如您所见,一个区间 inproducts可能与零个或多个 in 重叠,slowdown反之亦然。区间可靠地不会在同一个表中重叠。

对于和xdays之间的每个重叠,我需要计算为。productsslowdowntime_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 语句?

4

3 回答 3

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

小提琴

于 2013-03-14T16:15:55.437 回答
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

于 2013-03-14T16:16:48.100 回答
0

我会为每个计算编写 PL/SQL 函数并将它们调用到我的选择中以获得您想要的结果。在 SQL 中可能有一种方法可以做到这一点,但它会变得有点难看。

于 2013-03-14T15:48:16.157 回答