我目前的表结构是:
我想计算当天每个产品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)
;
答案 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