2013-12-17 18 views
6

Jestem nowy w Hive/SQL i utknąłem na dość prostym problemie. Moje dane wyglądają następująco:Uzyskaj wiersz z maksymalną wartością w Hive/SQL?

+------------+--------------------+-----------------------+ 
| carrier_iD |  meandelay  |  meancanceled  | 
+------------+--------------------+-----------------------+ 
| EV   | 13.795802119653473 | 0.028584251044292006 | 
| VX   | 0.450591016548463 | 2.364066193853424E-4 | 
| F9   | 10.898001378359766 | 0.00206753962784287 | 
| AS   | 0.5071547420965062 | 0.0057404326123128135 | 
| HA   | 1.2031093279839498 | 5.015045135406214E-4 | 
| 9E   | 8.147899230704216 | 0.03876067292247866 | 
| B6   | 9.45383857757506 | 0.003162096314343487 | 
| UA   | 8.101511665305816 | 0.005467725574605967 | 
| FL   | 0.7265068895709532 | 0.0041141513746490044 | 
| WN   | 7.156119279121648 | 0.0057419058192869415 | 
| DL   | 4.206288692245839 | 0.005123990066804269 | 
| YV   | 6.316802855264404 | 0.029304029304029346 | 
| US   | 3.2221527095063736 | 0.007984031936127766 | 
| OO   | 6.954715814690328 | 0.02596499362466706 | 
| MQ   | 9.74568222216328 | 0.025628100708354324 | 
| AA   | 8.720522654298968 | 0.019242775597574157 | 
+------------+--------------------+-----------------------+ 

Chcę, aby Hive zwrócił wiersz z wartością maxDayay. Mam:

SELECT CAST(MAX(meandelay) as FLOAT) FROM flightinfo; 

co rzeczywiście zwraca wartość maksymalną (używam rzutowania, ponieważ moje wartości są zapisane jako STRING). Tak więc:

SELECT * FROM flightinfo WHERE meandelay = (SELECT CAST(MAX(meandelay) AS FLOAT) FROM flightinfo); 

pojawia się następujący błąd:

FAILED: ParseException line 1:44 cannot recognize input near 'select' 'cast' '(' in expression specification 

Odpowiedz

0

Nie sądzę sub-query jest dozwolone ...

Szybkie spojrzenie tutaj:

https://cwiki.apache.org/confluence/display/Hive/LanguageManual+SubQueries

states:

As of Hive 0.13 some types of subqueries are supported in the WHERE clause. Those are queries where the result of the query can be treated as a constant for IN and NOT IN statements (called uncorrelated subqueries because the subquery does not reference columns from the parent query):

+0

Oh ... czy istnieje praktyczny sposób obejścia tego? – marc

0

Możesz użyć UDF collect_max z Brickhouse (http://github.com/klout/brickhouse), aby rozwiązać ten problem, przekazując wartość 1, co oznacza, że ​​chcesz uzyskać pojedynczą wartość maksymalną.

select array_index(map_keys(collect_max(carrier_id, meandelay, 1)), 0) from flightinfo; 

Również czytałem gdzieś, że Hive max UDF nie pozwalają na dostęp do innych pól w wierszu, ale myślę, że łatwiej jest używać collect_max.

2

zamiast tego użyj łączenia.

SELECT a.* FROM flightinfo a left semi join 
(SELECT CAST(MAX(meandelay) AS FLOAT) 
maxdelay FROM flightinfo)b on (a.meandelay=b.maxdelay) 
+0

Co dokładnie robi polecenie 'left semi join'? – vashts85

8

Użyj windowing and analytics functions

SELECT carrier_id, meandelay, meancanceled 
FROM 
(SELECT carrier_id, meandelay, meancanceled, 
     rank() over (order by cast(meandelay as float) desc) as r 
    FROM table) S 
WHERE S.r = 1; 

Będzie to również rozwiązać problem, jeśli więcej niż jeden rząd ma taką samą wartość max, dostaniesz wszystkie wiersze w wyniku. Jeśli chcesz zmienić pojedynczy wiersz rank() na row_number() lub dodaj kolejny termin do order by.

Powiązane problemy