【问题标题】:Extract EndDate from the StartDate column using SQL i.e two dates coming from the same column使用 SQL 从 StartDate 列中提取 EndDate,即来自同一列的两个日期
【发布时间】:2015-08-16 10:13:52
【问题描述】:

我现在的表结构是:

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

例如

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

【问题讨论】:

    标签: sql oracle


    【解决方案1】:

    你基本上想要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;
    

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

    【讨论】:

    • 谢谢,我理解了使用lead()的逻辑。我在工作代码下方发布。
    【解决方案2】:

    戈登的回答比较简单。但是,您也可以尝试使用ctes。

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

    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
    

    【讨论】:

    • 谢谢,但我对您的代码做了一些更改以获得我需要的东西。我已经发布了下面的代码。
    【解决方案3】:
    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;
    

    【讨论】:

      【解决方案4】:

      请尝试以下查询。这是特定于您提到的结构

      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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 2014-11-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2013-03-11
        • 1970-01-01
        相关资源
        最近更新 更多