使用SQL从StartDate列中提取EndDate,即来自同一列的两个日期

时间:2015-08-12 00:59:33

标签: sql oracle

我目前的表结构是:

enter image description here

我想计算当天每个产品ID的持续时间加权平均价格。

e.g。

PA1的平均价格=(100 * 4 + 105 * 4 + 110 * 8 + 115 * 4)/ 20

即此价格在4小时内保持100,在4小时内保持105,在8小时保持110,在4小时保持115(结束时间是午夜)

下面的Oracle SQL将帮助您快速创建表结构,谢谢。

CREATE TABLE ProductTable
(ID NUMBER(5), 
 ProdId varchar(7),
 StartDate DATE,
Price NUMBER(4));

INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (1, 'PA1', TO_DATE('2015/08/01 4:00', 'YYYY/MM/DD hh24:mi'), 100);
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (2, 'PA1', TO_DATE('2015/08/01 8:00', 'YYYY/MM/DD hh24:mi'), 105)
;
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (3, 'PA2', TO_DATE('2015/08/01 9:00', 'YYYY/MM/DD hh24:mi'), 120);
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (4, 'PA1', TO_DATE('2015/08/01 12:00', 'YYYY/MM/DD hh24:mi'), 110)
;
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (5, 'PA3', TO_DATE('2015/08/01 14:00', 'YYYY/MM/DD hh24:mi'), 150)
;
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (6, 'PA2', TO_DATE('2015/08/01 15:00', 'YYYY/MM/DD hh24:mi'), 130)
;
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (7, 'PA2', TO_DATE('2015/08/01 18:00', 'YYYY/MM/DD hh24:mi'), 125)
;
INSERT INTO ProductTable (ID, ProdId, StartDate, Price)
VALUES (8, 'PA1', TO_DATE('2015/08/01 20:00', 'YYYY/MM/DD hh24:mi'), 115)
;

4 个答案:

答案 0 :(得分:0)

你基本上想要lead()函数,然后是一些日期算术:

select prodid,
       sum((least(trunc(startdate + 1, next_startdate) - startdate)*24) numhours
from (select p.*, lead(startdate) over (order by startdate) as next_startdate
      from producttable t
     ) t
where date = date '2015-08-01'
group by prodid;

这是基于白天第一条记录的计算,这就是你在问题中描述结果的方式。

答案 1 :(得分:0)

戈登的回答更简单。但是,您也可以尝试使用cte s。

您还应该决定是否必须为某一天的某一天计算加权平均值。在这种情况下,它还需要在日期和年份进行分组。

SQL小提琴:http://sqlfiddle.com/#!4/0f4e6/6

with x as (
select
 prodid
,price
,extract(hour from cast(startdate as timestamp))
 -nvl(lag(extract(hour from cast(startdate as timestamp))) 
 over(partition by prodid order by startdate),0) timediff
 from producttable)
, y as(
  select prodid, sum(x.timediff*x.price) as sm, sum(timediff) stimediff
  from x
  group by prodid)
  select prodid, sm / stimediff weighted_avg
  from y

答案 2 :(得分:0)

with x as (
  select
  prodid,
  price,
  nvl(lead(extract(hour from cast(startdate as timestamp)))
   over (partition by prodid order by startdate), 24)
   - extract(hour from cast(startdate as timestamp)) as timediff
  from producttable),
y as (
select 
prodid, 
sum(x.timediff*x.price) as sm,
sum(x.timediff) as stimediff
from x
group by prodid)
select prodid, sm / stimediff as weightedAvg_Price
from y;

答案 3 :(得分:-1)

请在下面尝试此查询。这特定于您提到的结构

SELECT y.prodid,
       sum(y.price*y.hours_diff)/sum(hours_diff)
FROM
  (SELECT x.prodid,
          x.price,
          x.curr_prod_st_date,
          x.next_prod_st_date,
          round(to_char(to_date(x.next_prod_st_date,'dd-mon-yyyy hh24:mi:ss'),'hh24.miss')-to_char(to_date(x.curr_prod_st_date,'dd-mon-yyyy hh24:mi:ss'),'hh24.miss'),0)hours_diff
   FROM
     ( SELECT prod.*,
              to_char(prod.startdate,'dd-mon-yyyy hh24:mi:ss')curr_prod_st_date,
              nvl(lead(to_char(prod.startdate,'dd-mon-yyyy hh24:mi:ss'),1) over (partition BY prodid
                                                                                 ORDER BY prodid,id,price),to_char(trunc(prod.startdate)+1-1/86400,'dd-mon-yyyy hh24:mi:ss')) next_prod_st_date
      FROM producttable prod)x)y
GROUP BY y.prodid