Spark SQL sql ("<некоторый совокупный запрос>"). First(). GetDouble(0) дают мне противоречивые результаты
У меня есть запрос ниже, который должен найти среднее значение столбца и вернуть мне результат, который является одним числом.
val avgVal = hiveContext.sql("select round(avg(amount), 4) from users.payment where dt between '2018-05-09' and '2018-05-09'").first().getDouble(0)
Я сталкиваюсь с непоследовательным поведением в этом заявлении. Это часто терпит неудачу с ошибкой ниже, однако это дает отличные от NULL результаты при выполнении через Hive.
18/05/10 11:01:12 ERROR ApplicationMaster: User class threw exception: java.lang.NullPointerException: Value at index 0 in null
java.lang.NullPointerException: Value at index 0 in null
at org.apache.spark.sql.Row$class.getAnyValAs(Row.scala:475)
at org.apache.spark.sql.Row$class.getDouble(Row.scala:243)
at org.apache.spark.sql.catalyst.expressions.GenericRow.getDouble(rows.scala:192)
Причина, по которой я использую HiveContext вместо SQLContext, заключается в том, что последний не поддерживает некоторые функции агрегирования, которые я широко использую в своем коде.
Не могли бы вы помочь мне понять, почему эта проблема возникает и как ее решить?
2 ответа
Вам нужно разделить запрос и разбить его на две части:
var result = hiveContext.sql("select round(avg(amount), 4) from users.payment where dt between '2018-05-09' and '2018-05-09'");
var first = result.first();
if (first != null && !first.isNullAt(0)) {
var avgVal = first.getDouble(0);
}
Это позволит избежать NPE. Это также будет необходимо в списке и массиве.
Для вставки или обновления запроса вам даже нужно try...catch
блок для отлова исключения во время выполнения.
Давайте проанализируем случай и возможные причины, когда это исключение может быть выброшено.
Row row = hiveContext.sql("select info, name, desc, id from users.payment where dt between '2018-05-09' and '2018-05-09'").first();
Если значение row
выше возвращено что-то вроде:
[null, Kevin, cash, 300]
Пытаясь получить getDouble(0)
приведет к java.lang.NullPointerException: Value at index 0 in null
Вы можете попробовать следующий подход:
Row row = hiveContext.sql("select round(avg(amount), 4) from users.payment where dt between '2018-05-09' and '2018-05-09'").first();
if (!row.isNullAt(0))
double d = row.getDouble(0);
else
logger.error("Value at index zero is null");
Если вы проверите источники, класс библиотеки делает наоборот:
private static Object getAnyValAs(Row $this, int i) {
if($this.isNullAt(i)) {
throw new NullPointerException((new StringContext(scala.Predef..MODULE$.wrapRefArray((Object[])(new String[]{"Value at index ", " is null"})))).s(scala.Predef..MODULE$.genericWrapArray(new Object[]{BoxesRunTime.boxToInteger(i)})));
} else {
return $this.getAs(i);
}
}