2016-03-15 2 views
1

Я разработал следующую функцию для работы с массивами любого числового типа:функция SparkSQL требуют типа Decimal

def array_sum[T](item:Traversable[T])(implicit n:Numeric[T]) = item.sum 
// Registers a function as a UDF so it can be used in SQL statements. 
sqlContext.udf.register("array_sumD", array_sum(_:Seq[Float])) 

Но желающих передать массив типа плывут мне следующую ошибку:

// Now we can use our function directly in SparkSQL. 
sqlContext.sql("SELECT array_sumD(array(5.0,1.0,2.0)) as array_sum").show 

Ошибка:

cannot resolve 'UDF(array(5.0,1.0,2.0))' due to data type mismatch: argument 1 requires array<double> type, however, 'array(5.0,1.0,2.0)' is of array<decimal(2,1)> type; 

ответ

1

Тип данных по умолчанию для десятичных значений в Spark-SQL - это нудичность. Если вы отливать ваши литералов в запросе на поплавках, и использовать тот же UDF, он работает:

sqlContext.sql(
    """SELECT array_sumD(array(
    | CAST(5.0 AS FLOAT), 
    | CAST(1.0 AS FLOAT), 
    | CAST(2.0 AS FLOAT) 
    |)) as array_sum""".stripMargin).show 

Результат, как и ожидалось:

+---------+ 
|array_sum| 
+---------+ 
|  8.0| 
+---------+ 

Альтернативно, если вы сделать хотите использовать десятичные знаки (чтобы избежать проблем с плавающей запятой), вы будете еще должны использовать литье, чтобы получить право точность, плюс вы не будете abl e для использования Scala's nice Numeric и sum, в виде десятичных знаков считаются java.math.BigDecimal. Таким образом, ваш код будет:

def array_sum(item:Traversable[java.math.BigDecimal]) = item.reduce((a, b) => a.add(b)) 

// Registers a function as a UDF so it can be used in SQL statements. 
sqlContext.udf.register("array_sumD", array_sum(_:Seq[java.math.BigDecimal])) 

sqlContext.sql(
    """SELECT array_sumD(array(
    | CAST(5.0 AS DECIMAL(38,18)), 
    | CAST(1.0 AS DECIMAL(38,18)), 
    | CAST(2.0 AS DECIMAL(38,18)) 
    |)) as array_sum""".stripMargin).show 
Смежные вопросы