2014-10-21 2 views
0

У меня есть таблица, какЛучший способ создать процентные диапазоны в оракула 11gr2

Value Average Difference% 
1  2   50 
5.5  13   43 
3  10   30 

И я хочу, чтобы превратить это в нечто вроде

Difference Range # 
0-30    1 
41-50    2 

Чтобы впоследствии сюжет, который в гистограмм, как граф ,

После того, как я написал типичный case when difference < 10 then 'under 10%' else when ... end, я начал задаваться вопросом, есть ли лучший способ сделать это. Нашел PERCENT_RANK, который, казалось, шел именно так, но не совсем то, что я искал.

Было бы лучше, если бы шаг из бушует фиксировались, как, каждый 5%:

case 
    when dif_perc_med = 0 then 'Ok' 
    when dif_perc_med < 0.05 then 'até 5%' 
    when dif_perc_med < 0.1 then 'até 10%' 
    when dif_perc_med < 0.15 then 'até 15%' 
    when dif_perc_med < 0.2 then 'até 20%' 
    when dif_perc_med < 0.25 then 'até 25%' 
    when dif_perc_med < 0.3 then 'até 30%' 
    when dif_perc_med < 0.35 then 'até 35%' 
    when dif_perc_med < 0.4 then 'até 40%' 
    when dif_perc_med < 0.45 then 'até 45%' 
    when dif_perc_med < 0.5 then 'até 50%' 
    when dif_perc_med < 0.55 then 'até 55%' 
    when dif_perc_med < 0.6 then 'até 60%' 
    when dif_perc_med < 0.65 then 'até 65%' 
    when dif_perc_med < 0.7 then 'até 70%' 
    when dif_perc_med < 0.75 then 'até 75%' 
    when dif_perc_med < 0.8 then 'até 80%' 
    when dif_perc_med < 0.85 then 'até 85%' 
    when dif_perc_med < 0.9 then 'até 90%' 
    when dif_perc_med < 0.95 then 'até 95%' 
else 'mais de 95%'end as rng_perc_dif 

Любые идеи?

+0

Может 'width_bucket' является то, что вы ищете? http://docs.oracle.com/cd/E11882_01/server.112/e41084/functions234.htm#SQLRF06163 –

+0

именно то, что мне нужно. хотите превратить это в ответ? благодаря! – filippo

ответ

1

Вы можете использовать простые арифметику, чтобы сделать это:

SELECT TRUNC("Difference"/5) "Rank", COUNT("Difference") 
FROM T 
GROUP BY TRUNC("Difference"/5); 

Если вам нужно все значения (. Включая «отсутствующий» те), вы можете использовать объединение в некоторой сгенерированной таблице:

SELECT ("Rank")*5 "From", ("Rank"+1)*5 "To", NVL(V."Cnt", 0) "Cnt" 
--   from N   to N+1 
FROM (
    SELECT LEVEL-1 "Rank" FROM DUAL CONNECT BY LEVEL <= 100/5 
    --   ^^ 
    -- start from zero 
) C 
LEFT JOIN (
    SELECT TRUNC("Difference"/5) "Rank", COUNT("Difference") "Cnt" 
    FROM T 
    GROUP BY TRUNC("Difference"/5) 
) V 
USING("Rank") 
ORDER BY "Rank" 

В этом примере я жестко закодировал все 5 - для производственного кода вы должны, вероятно, включить их в параметры.


Начиная с 10г (я думаю) Oracle поддерживает функцию WIDTH_BUCKET, которые выполняют в основном ту же работу, как и выше арифметика. Таким образом, вы могли бы переписать этот запрос, как это:

SELECT ("Rank"-1)*5 "From", ("Rank")*5 "To", COUNT(V.ROWID) "Cnt" 
--   from N-1   to N 
FROM (
    SELECT LEVEL "Rank" FROM DUAL CONNECT BY LEVEL <= 100/5 
    --  ^^ 
    -- start from one 
) C 
LEFT JOIN (
    SELECT WIDTH_BUCKET("Difference",0,100,20) "Rank" 
    FROM T 
) V 
USING("Rank") 
GROUP BY "Rank" 
ORDER BY "Rank"; 

Посмотреть http://sqlfiddle.com/#!4/d7398/29 для живого испытания этих различных решений

+0

wait. какие. теперь я чувствую себя глупо. В любом случае, комментарий от @a_horse_with_no_name - именно то, что я искал. Спасибо хоть. – filippo

+0

@filippo;) Для справки вы могли бы разместить самопринятый ответ, изображающий, как вы использовали 'WIDTH_BUCKET' для решения вашей проблемы? –

Смежные вопросы