Spark SQL sql ("<некоторый совокупный запрос>"). First (). GetDouble (0) дают мне противоречивые результаты - PullRequest
0 голосов
/ 10 мая 2018

У меня есть запрос ниже, который должен найти среднее значение столбца и вернуть мне результат, который является одним числом.

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 ]

0 голосов
/ 10 мая 2018

Давайте проанализируем случай и возможные причины, когда это исключение может быть выдано.

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);
    }
}
0 голосов
/ 10 мая 2018

Вам нужно разделить запрос и разбить его на две части:

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, чтобы перехватить исключение времени выполнения.

...