2017-03-07 8 views
0

タイムスタンプを時刻を表す整数に変換するUDFを作成しようとしています。私はこのようなSparkSqlでこれを簡単に達成することができます。Spark UDFタイプの不一致エラー

enter image description here

私はこの正確な構文で我々のコードの多くのUDFを持っていますが、この1は、型の不一致エラーをしようとしています。私もcol("session_ts_start")でUDFを呼び出そうとしましたが、それもうまくいきませんでした。

import spark.implicits._ 
import java.sql.Timestamp 
import org.apache.spark.sql.functions._ 

def getHourOfWeek() = udf(
    (ts: Timestamp) => unix_timestamp(ts) 
) 

val dDF = df.withColumn("hour", getHourOfWeek()(df("session_ts_start"))) 
dDF.show() 

<console>:154: error: type mismatch; 
found : java.sql.Timestamp 
required: org.apache.spark.sql.Column 
      (ts: Timestamp) => unix_timestamp(ts) 

答えて

0

unix_timestampはSQL関数です。それoperates on Columnsない外部値:

def unix_timestamp(s: Column): Column 

、それはUDFで使用することはできません。

私がしようとしている(...)は、一週間の時間を表す整数にタイムスタンプを変換する

import org.apache.spark.sql.Column 
import org.apache.spark.sql.functions.{date_format, hour} 

def getHourOfWeek(c: Column) = 
    // https://docs.oracle.com/javase/8/docs/api/java/text/SimpleDateFormat.html 
    (date_format(c, "u").cast("integer") - 1) * 24 + hour(c) 

val df = Seq("2017-03-07 01:00:00").toDF("ts").select($"ts".cast("timestamp")) 

df.select(getHourOfWeek($"ts").alias("hour")).show 
+----+ 
|hour| 
+----+ 
| 25| 
+----+ 

もう1つの可能な解決策:

import org.apache.spark.sql.functions.{next_day, date_sub} 

def getHourOfWeek2(c: Column) = ((
    c.cast("bigint") - 
    date_sub(next_day(c, "Mon"), 7).cast("timestamp").cast("bigint") 
)/3600).cast("int") 

df.select(getHourOfWeek2($"ts").alias("hour")) 
+----+ 
|hour| 
+----+ 
| 25| 
+----+ 

:いずれのソリューションも夏時間やその他の日時微妙な問題を処理しません。

関連する問題