web-dev-qa-db-fra.com

Obtenir une ligne avec une valeur maximale dans Hive/SQL?

Je suis nouveau sur Hive/SQL et je suis bloqué sur un problème assez simple. Mes données ressemblent à:

+------------+--------------------+-----------------------+
| 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  |
+------------+--------------------+-----------------------+

Je veux que Hive renvoie la ligne avec la valeur meanDelay max. J'ai:

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

qui renvoie effectivement le maximum (j’utilise cast parce que mes valeurs sont enregistrées en tant que chaîne) Donc alors:

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

Je reçois l'erreur suivante:

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

Utilisez les fonctions de fenêtrage et d'analyse

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;

Cela résoudra également le problème si plus d'une ligne a la même valeur maximale, vous obtiendrez toutes les lignes comme résultat. Si vous souhaitez simplement une seule ligne, remplacez rank() par row_number() ou ajoutez un autre terme au order by.

9
libjack

utilisez plutôt join.

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

Vous pouvez utiliser le fichier UDF collect_max de Brickhouse ( http://github.com/klout/brickhouse ) pour résoudre ce problème en transmettant la valeur 1, ce qui signifie que vous ne souhaitez que la valeur max unique.

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

De plus, j'ai lu quelque part que la valeur UDF Hive max vous permet d'accéder à d'autres champs de la rangée, mais je pense qu'il est plus facile d'utiliser simplement collect_max.

1
Jerome Banks

Je ne pense pas que votre sous-requête est autorisée ...

Un coup d'oeil ici:

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

États:

A partir de Hive 0.13, certains types de sous-requêtes sont pris en charge dans la clause WHERE. Ce sont des requêtes où le résultat de la requête peut être traité comme une constante pour les instructions IN et NOT IN (appelées sous-requêtes non corrélées car la sous-requête ne référence pas les colonnes de la requête parent):

0
BWS