2015-08-07 12 views
6

Derzeit, um eine Spalte im Bienenstock Rang zu bewerten, verwende ich etwas wie folgt. Ich versuche, Elemente in einer Spalte nach dem Prozentsatz zu ordnen, unter dem sie fallen, und weisen jedem Element einen Wert von 0 bis 1 zu. Der folgende Code weist einen Wert zwischen 0 und 9 zu, der besagt, dass ein Artikel mit char_percentile_rank von 0 in den unteren 10% der Artikel und ein Wert von 9 in den oberen 10% der Artikel enthalten ist. Gibt es einen besseren Weg, dies zu tun?Hive: Gibt es einen besseren Weg, eine Spalte in Prozent zu ranken?

select item 
    , characteristic 
    , case when characteristic <= char_perc[0] then 0 
     when characteristic <= char_perc[1] then 1 
     when characteristic <= char_perc[2] then 2 
     when characteristic <= char_perc[3] then 3 
     when characteristic <= char_perc[4] then 4 
     when characteristic <= char_perc[5] then 5 
     when characteristic <= char_perc[6] then 6 
     when characteristic <= char_perc[7] then 7 
     when characteristic <= char_perc[8] then 8 
     else 9 
     end as char_percentile_rank 
from (
    select split(item_id,'-')[0] as item 
     , split(item_id,'-')[1] as characteristic 
     , char_perc 
    from (
     select collect_set(concat_ws('-',item,characteristic)) as item_set 
      , PERCENTILE(BIGINT(characteristic),array(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)) as char_perc 
     from(
      select item 
       , sum(characteristic) as characteristic 
      from table 
      group by item 
     ) t1 
    ) t2 
    lateral view explode(item_set) explodetable as item_id 
) t3 

Hinweis: Ich hatte die collect_set zu tun, um einen Selbst zu vermeiden verbinden, da die Perzentil-Funktion implizit ein group by führt.

Ich habe festgestellt, dass die Perzentil-Funktion schrecklich langsam ist (zumindest in dieser Verwendung). Vielleicht wäre es besser, Perzentil manuell zu berechnen?

Antwort

4

Versuche eines Ihrer abgeleitete Tabellen entfernen

select item 
    , characteristic 
    , case when characteristic <= char_perc[0] then 0 
     when characteristic <= char_perc[1] then 1 
     when characteristic <= char_perc[2] then 2 
     when characteristic <= char_perc[3] then 3 
     when characteristic <= char_perc[4] then 4 
     when characteristic <= char_perc[5] then 5 
     when characteristic <= char_perc[6] then 6 
     when characteristic <= char_perc[7] then 7 
     when characteristic <= char_perc[8] then 8 
     else 9 
     end as char_percentile_rank 
from (
    select item, characteristic, 
     , PERCENTILE(BIGINT(characteristic),array(0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)) over() as char_perc 
    from (
     select item 
     , sum(characteristic) as characteristic    
     from table 
     group by item    
    ) t1 
) t2 
+0

Die Perzentil-Funktion, um eine Gruppe haben, muss durch - das ist, warum ich die scheinbar unnötige collect_set tat (CONCAT_WS (...)) -, um es zu machen Gruppe. Wenn ich stattdessen nach Artikel und Merkmal gruppiere, dann werden Perzentile nach Artikel und Merkmal, die ich nicht möchte. Irgendwelche Ideen, wie man das vermeidet? –

+1

Ich fand es fast sofort heraus, nachdem ich darauf geschlafen hatte und zurückkam. Fügen Sie einfach per() auf das Perzentil hinzu. Die Zeile sollte also lauten: PERCENTILE (BIGINT (Charakteristik), Array (0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9)) over() als char_perc. Aber es scheint, dass sowohl meine ursprüngliche Abfrage als auch die neue sehr ähnliche Leistung haben. –

+0

@CharlieHaley ist es möglich, auf "PERCENTILE (BIGINT ...) [i]" zu verweisen, wobei "i = 0-8" ist? Wenn ja, können Sie die case-Anweisung verschieben und 1 abgeleitete Tabelle entfernen – FuzzyTree

Verwandte Themen