Как сделать максимальное количество (*) с помощью Hive?

У меня есть две таблицы:

Летать: Год, Происхождение

Аэропорт : Код, Название

Вот пример данных:

Полет :

1989,SF    
1989,SF   
1989,NY  
1993,NY  
1998,Par     
1998,Par  
1998,NY

Аэропорт :

SF, International Airport    
NY, Inter Air    
Par, Charles de Gaulle

Я хочу получить самый используемый аэропорт в год.

Итак, во-первых, я сделал этот запрос, чтобы получить количество появлений каждого аэропорта за каждый год:

SELECT v.Year,a.airport ,count(*)
From airports a JOIN Vol v ON (a.iata = v.Dest)
Group By v.Year,a.airport
ORDER BY Year ASC,airport ASC;

Итак, я получаю такой результат:

1989, San Francisco, 2  
1989, New York, 1
1993, New York, 1
1998, new York, 1
1998, Paris, 2

И я хочу, чтобы каждый год был максимальным:

1989, San Francisco, 2
1993, New York, 1
1998, Paris, 2

Могу ли я сделать это одним запросом? Должен ли я использовать промежуточную таблицу?

Со свиньей лучше?

заранее спасибо


person Junayy    schedule 27.05.2014    source источник


Ответы (1)


Это немного сложно в Hive, но, безусловно, выполнимо. Для этого требуются две вещи: использование вашего первого запроса в качестве подзапроса для более крупного и небольшая хитрость для выполнения «arg-max».

SELECT Year, max(named_struct('n', n, 'airport', airport)) FROM (
  SELECT v.Year, a.airport, count(*) as n
  FROM airports a JOIN Vol v ON (a.iata = v.Dest)
  GROUP BY v.Year, a.airport
) t
GROUP BY Year;

Обратите внимание, что named_struct создает поле структуры, и они сначала сравниваются в порядке их первого поля, поэтому вы получаете правильное «максимальное» поведение, сохраняя при этом имя аэропорта. Это означает, что ваш вывод будет иметь форму структуры:

1989, {n:2, airport:San Francisco}
1993, {n:1, airport:New York}
1998, {n:2, airport:Paris}

Если вы хотите «не структурировать» его, вам просто нужно выбрать эти поля по отдельности:

SELECT Year, max(named_struct('n', n, 'airport', airport)).n, max(named_struct('n', n, 'airport', airport)).airport FROM (
  SELECT v.Year, a.airport, count(*) as n
  FROM airports a JOIN Vol v ON (a.iata = v.Dest)
  GROUP BY v.Year, a.airport
) t
GROUP BY Year;
person Joe K    schedule 27.05.2014
comment
Также вы должны использовать count(1), а не count(*), это намного эффективнее, так как не будет анализировать данные в строке для выполнения подсчета. - person feldoh; 28.05.2014
comment
Спасибо, это именно то, что мне было нужно. Но что касается count(1) и count(*) я не замечаю никаких различий в производительности. - person Junayy; 28.05.2014