【问题标题】:Oracle 11g: How I get best value of each step when I don't have all stepsOracle 11g:当我没有所有步骤时如何获得每个步骤的最佳价值
【发布时间】:2017-09-06 17:17:01
【问题描述】:

我必须在 2 个列表之间为每个步骤选择最佳百分比。但是,如示例所示,我可能不会在两个列表中包含所有步骤。

鉴于我在表中有以下值列表:

LIST_NUMBER     MAX_POINTS      PERCENTAGE
------------------------------------------
          1             79             20%
          1            150             25%
          1           9999             30%


LIST_NUMBER     MAX_POINTS      PERCENTAGE
------------------------------------------
          2             79             20%
          2           9999             35%

如果我得到MAX(PERCENTAGE)GROUP BY MAX_POINTS,我会得到以下结果:

SELECT MAX_POINTS,
  MAX (PERCENTAGE)
   FROM MY_TABLE
  GROUP MAX_POINTS
  ORDER BY MAX_POINTS ;


MAX_POINTS   MAX(PERCENTAGE)
----------------------------
        79               20
       150               25
     99999               35

这是不对的,因为第二个列表说我只要得到 80+ 分就应该有 35%。 我期望的结果是这样的:

MAX_POINTS   MAX(PERCENTAGE)
----------------------------
        79               20
       150               35
     99999               35

我可以列出我可以拥有的所有MAX_POINTS(包括两个列表)和每个步骤的百分比(MAX_POINTS),但我会在MAX_POINTS = 15LIST_NUMBER = 2 得到NULL

LIST_NUMBER      MAX_POINTS      MAX(PERCENTAGE)
------------------------------------------------
          1           79                     20%
          1           150                    25%
          1           99999                  30%
          2           79                     20%
          2           150                   NULL <- This value should be the next non-null value of the LIST_NUMBER = 2 = 35%
          2           99999                  35%

【问题讨论】:

    标签: sql oracle oracle11g


    【解决方案1】:

    只有两个列表首先在MAX_POINTcolumn 上执行两个列表的完全外连接

    select 
    nvl(a.MAX_POINTS,b.MAX_POINTS) MAX_POINTS, a.PERCENTAGE PERCENTAGE1, b.PERCENTAGE PERCENTAGE2
    from (select MAX_POINTS,  PERCENTAGE from my_lst where LIST_NUMBER = 1) a
    full outer join (select MAX_POINTS,  PERCENTAGE from my_lst where LIST_NUMBER = 2) b 
    on a.MAX_POINTS = b.MAX_POINTS
    ;
    
    MAX_POINTS PERCENTAGE1 PERCENTAGE2
    ---------- ----------- -----------
            79          20          20 
           150          25             
          9999          30          35 
    

    现在您有了一个唯一列表,其中包含两个列表中的所有 MAX_POINTs 以及已知百分比。

    在下一步中,您必须填写两个列表中缺失的百分比(PERCENTAGE1PERCENTAGE 列中的 NULL)。使用带有后代排序的解析MIN函数。

    with step1 as (      
    select 
    nvl(a.MAX_POINTS,b.MAX_POINTS) MAX_POINTS, a.PERCENTAGE PERCENTAGE1, b.PERCENTAGE PERCENTAGE2
    from (select MAX_POINTS,  PERCENTAGE from my_lst where LIST_NUMBER = 1) a
    full outer join (select MAX_POINTS,  PERCENTAGE from my_lst where LIST_NUMBER = 2) b 
    on a.MAX_POINTS = b.MAX_POINTS)
    select 
    MAX_POINTS, 
    min(PERCENTAGE1) over (order by MAX_POINTS desc) PERCENTAGE1, 
    min(PERCENTAGE2) over (order by MAX_POINTS desc) PERCENTAGE2 
    from step1
    order by MAX_POINTS
    ;
    
    MAX_POINTS PERCENTAGE1 PERCENTAGE2
    ---------- ----------- -----------
            79          20          20 
           150          25          35 
          9999          30          35 
    

    在最后一步中,您只需要获得每个 POINT 的最高百分比 - GREATEST函数会为您完成:

    with step1 as (      
    select 
    nvl(a.MAX_POINTS,b.MAX_POINTS) MAX_POINTS, a.PERCENTAGE PERCENTAGE1, b.PERCENTAGE PERCENTAGE2
    from (select MAX_POINTS,  PERCENTAGE from my_lst where LIST_NUMBER = 1) a
    full outer join (select MAX_POINTS,  PERCENTAGE from my_lst where LIST_NUMBER = 2) b 
    on a.MAX_POINTS = b.MAX_POINTS),
    step2 as (
    select 
    MAX_POINTS, 
    min(PERCENTAGE1) over (order by MAX_POINTS desc) PERCENTAGE1, 
    min(PERCENTAGE2) over (order by MAX_POINTS desc) PERCENTAGE2 
    from step1)
    select MAX_POINTS, 
    GREATEST(PERCENTAGE1,PERCENTAGE2) PERCENTAGE
    from step2
    order by MAX_POINTS;   
    
    MAX_POINTS PERCENTAGE
    ---------- ----------
            79         20 
           150         35 
          9999         35
    

    【讨论】:

      【解决方案2】:

      如果我理解正确:

      select l.list_number, p.max_points,
             coalesce(t.value,
                      lead(t.value ignore nulls) over (partition by l.list_number or by p.max_points)
                     ) as value
      from (select distinct list_number from t) l cross join
           (select distinct max_points from t) p left join
           t
           on t.list_number = l.list_number and t.max_points = p.max_points;
      

      cross join 生成所有行——所有列表和所有max_points。如果需要,lead() 会获取下一个非NULL 值。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-04-09
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2020-12-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多