Oracle 11g:当我没有完成所有步骤时,我如何获得每个步骤的最佳价值

时间:2017-04-11 10:53:10

标签: sql oracle oracle11g

我必须为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)的PERCENTAGE但我会在MAX_POINTS = 15 LIST_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%

2 个答案:

答案 0 :(得分:0)

如果我理解正确:

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值。

答案 1 :(得分:0)

只有两个列表首先在MAX_POINT列上执行两个列表的完全外部联接

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_POINT的唯一列表以及已知百分比。

在下一步中,您必须填写两个列表中的缺失百分比(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