2014-05-02 13 views
5

muszę rangi wiersze autorem partycji (lub grupy), to znaczy, jeśli mój stół źródłem jest:Get kolejny numer wiersza (Ranking) wewnątrz partycji bez użycia ROW_NUMBER() OVER funkcji

NAME PRICE 
---- ----- 
AAA 1.59 
AAA 2.00 
AAA 0.75 
BBB 3.48 
BBB 2.19 
BBB 0.99 
BBB 2.50 

bym jak dostać stolik docelowa:

RANK NAME PRICE 
---- ---- ----- 
1 AAA 0.75 
2 AAA 1.59 
3 AAA 2.00 
1 BBB 0.99 
2 BBB 2.19 
3 BBB 2.50 
4 BBB 3.48 

Normalnie używam ROW_NUMBER() OVER funkcję, więc w Apache Hive byłoby:

select 
    row_number() over (partition by NAME order by PRICE) as RANK, 
    NAME, 
    PRICE 
from 
    MY_TABLE 
; 

Niestety Cloudera Impala nie obsługuje (w tej chwili) funkcji ROW_NUMBER() OVER, więc szukam obejścia. Najlepiej nie używać UDAF, ponieważ politycznie trudno będzie przekonać do wdrożenia go na serwerze.

Dziękuję za pomoc.

+1

funkcji analitycznych okienne są najwyższym priorytetem, a rozwój jest w toku. Bądź na bieżąco z nadchodzącym wydaniem, dodając tę ​​funkcjonalność jako część mapy drogowej do Impala 2.0. – Matt

Odpowiedz

2

Zazwyczaj obejście systemach nie obsługujących funkcji okna jest coś takiego:

select name, 
     price, 
     (select count(*) 
     from my_table t2 
     where t2.name = t1.name -- this is the "partition by" replacement 
     and t2.price < t1.price) as row_number 
from my_table t1 
order by name, price; 

SQLFiddle przykład: http://sqlfiddle.com/#!2/3b027/2

+0

Próbowałem tego, ale niestety Impala nie obsługuje obecnie podkwerend. –

3

Jeśli nie można tego zrobić z podzapytanie skorelowane, nadal można to zrobić z przyłączenia:

select t1.name, t1.price, 
     coalesce(count(t2.name) + 1, 1) 
from my_table t1 join 
    my_table t2 
    on t2.name = t1.name and 
     t2.price < t1.price 
order by t1.name, t1.price; 

Zauważ, że to nie dokładnie zrobić row_number()chyba wszystkie ceny są różne dla danego name. To sformułowanie jest faktycznie równoważne z rank().

Dla row_number() potrzebny jest unikalny identyfikator rzędu.

Nawiasem mówiąc, po to odpowiednik dense_rank():

select t1.name, t1.price, 
     coalesce(count(distinct t2.name) + 1, 1) 
from my_table t1 join 
    my_table t2 
    on t2.name = t1.name and 
     t2.price < t1.price 
order by t1.name, t1.price; 
+0

Zamiast łączenia wewnętrznego możliwe jest również lewe połączenie, w którym można zrzucić "część koalescencji (..., 1). –

0

Nie naprawdę odpowiedzią na jak z Impala, ale istnieją inne SQL na rozwiązaniach Hadoop, które mają już możliwości analityczne i podzapytania. Bez tych możliwości prawdopodobnie będziesz musiał polegać na procesie wieloetapowym lub na niektórych UDAF.

Jestem architektem InfiniDB
InfiniDB obsługuje funkcje analityczne i podzapytania.
http://infinidb.co

Wyjazd Query 8 w benchmarku z Radiant Advisors, to zapytanie styl podobny, że jesteś po, wykorzystując funkcję analityczną rangi. Presto jest również w stanie uruchomić tej kwerendy stylu, tylko w wolniejszym (80x) tempie http://radiantadvisors.com/wp-content/uploads/2014/04/RadiantAdvisors_Benchmark_SQL-on-Hadoop_2014Q1.pdf

Zapytanie od benchmarku (zapytania 8)

SELECT 
    sub.visit_entry_idaction_url, 
    sub.name, 
    lv.referer_url, 
    sum(visit_ total_time) total_time, 
    count(sub.idvisit), 
    RANK() OVER (PARTITION BY sub. visit_entry_idaction_url 
ORDER BY 
    count(sub.idvisit)) rank_by_visits, 
    DENSE_RANK() OVER (PARTITION BY sub.visit_entry_idaction_url 
ORDER BY 
    count(visit_total_time)) rank_by_ time_spent 
FROM 
    log_visit lv, 
    (
SELECT 
    visit_entry_idaction_url, 
    name, 
    idvisit 
FROM 
    log_visit JOIN log_ action 
     ON 
     (visit_entry_idaction_url = log_action.idaction) 
WHERE 
    visit_ entry_idaction_url between 2301400 AND 
    2302400) sub 
WHERE 
    lv.idvisit = sub.idvisit 
GROUP BY 
    1, 2, 3 
ORDER BY 
    1, 6, 7; 

Wyniki

Hive 0.12  Not Executable 
Presto 0.57  506.84s 
InfiniDB 4.0 6.37s 
Impala 1.2  Not Executable 
Powiązane problemy