当前位置: 首页 > 知识库问答 >
问题:

我用Java编写了一个sparksql UDF,但似乎有些地方出了问题

杨豪
2023-03-14

我的项目的整个依赖关系如下代码所示:

<dependencies>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-core_2.11</artifactId>
        <version>2.1.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-sql_2.11</artifactId>
        <version>2.1.2</version>
    </dependency>

    <dependency>
        <groupId>org.apache.spark</groupId>
        <artifactId>spark-hive_2.11</artifactId>
        <version>2.1.2</version>
    </dependency>

</dependencies>

我想用udf来计算两个格式为'yyyy-mm-ss hh:mm:ss.ss'的输入日期字符串之间的时间间隔(例如'2017-12-26 00:00:02.044'),结果将加倍,精度达到毫秒,例如,当我传递“2017-12-26 00:00:02.044”、“2017-12-26 00:00:03.045”给udf时,结果将是1.001秒,然后附带Java代码段:

import org.apache.commons.lang.StringUtils;
import org.apache.spark.sql.api.java.UDF2;

import java.text.SimpleDateFormat;
import java.util.Date;

public class DateDistance implements UDF2<String,String,Double> {

    public Double call(String s, String s2) throws Exception {
        Double result=0D;
        if(StringUtils.isNotBlank(s)&&StringUtils.isNotBlank(s2)){
            SimpleDateFormat sdf = new SimpleDateFormat("yyyy-mm-ss HH:mm:ss.SSS");
            Date parse = sdf.parse(s);
            Date parse2=sdf.parse(s2);
            Long milisecond1= parse.getTime();
            Long milisecond2= parse2.getTime();
            Long abs = Math.abs(milisecond1 - milisecond2);
            result = (abs.doubleValue()) / 1000D;
        }
        return result;
    }
}

使用UDF的步骤如下:

  1. 添加jar/home/hulk/learning/datedistance-1.0-snapshot.jar
  2. 将临时函数tmp_date_distance创建为“com.test.datedistance.datedistance”
  3. 使用SQL测试UDF:
Select tmp_date_distance('2017-12-26 00:00:02.044','2017-12-26
00:00:03.045') from stg.car_fact_order where dt='2018-01-09' limit 1;

之后,我得到了以下提示:

Error in query: No handler for Hive UDF 'com.sqyc.datedistance.DateDistance'; line 1 pos 7

你能给我一些建议吗?

共有1个答案

凌宏大
2023-03-14

第二步不正确:

将临时函数tmp_date_distance创建为“com.test.datedistance.datedistance”

Spark UDF与配置单元不兼容,应使用

sqlContext.udf().register(name, object, type);

或(2.0或更高版本):

spark.udf().register(name, object, type);

但您不需要UDF:

SELECT ABS(
       CAST(CAST('2017-12-26 00:00:02.044' AS TIMESTAMP) AS DOUBLE) - 
       CAST(CAST('2017-12-26 00:00:03.045' AS TIMESTAMP) AS DOUBLE) ) AS diff

+-----------------+
|             diff|
+-----------------+
|1.001000165939331|
+-----------------+

或四舍五入:

SELECT ROUND(ABS(
       CAST(CAST('2017-12-26 00:00:02.044' AS TIMESTAMP) AS DOUBLE) - 
       CAST(CAST('2017-12-26 00:00:03.045' AS TIMESTAMP) AS DOUBLE)), 3) AS diff

+-----+
| diff|
+-----+
|1.001|
+-----+
 类似资料:
  • 我正试图使Filepond工作,但CSS中的这一行似乎破坏了它-在ul选择器中。 我试着对页面的整个部分进行核化,直到Filepond起作用,将目标锁定在css上,最后在ul{}中找到前面提到的行。我可以把其他的东西都抹掉,只留下那条线,而文件孔仍然坏了,所以我肯定这是问题所在,但我不知道是怎么回事。 我尝试使用Chrome的检查器功能查看运行时页面源代码,但在那里找不到溢出。 然后我使用Note

  • 我正在使用Mapstruct v1.4.1.Final将Hibernate实体映射到相应的DTO。我使用Spring Boot,所以我的映射器的类具有等于的。 我有2个实体,和。包含一个实例: 人 地址 这是我写的地图: 地图绘制者 您可以看到,我对< code>PersonMapper说使用< code>AddressMapper来使用它的实现。 但是,为了将地址转换为地址dto,我在类中找到了

  • G6谁了解。加我一下。问个东西。我写不出来了啊? 结果我画的是这样的

  • 问题内容: 如果我在节点中编写以下程序: 然后在服务器上单击两次,在服务器上看到两次- 我不确定为什么单个HTTP请求导致两次执行。 问题答案: 那是正常现象-您的浏览器拨打了多个电话。 例如,大多数浏览器都会呼叫来获取。 尝试记录网址: 然后您会看到正在调用的内容。

  • 有许多有限状态机提出的问题,但都与我的问题无关。 我需要5种方法 我们从里面开始 我们想打印状态→ 0和输出0→ 读取输入首先在ebx中,第二个将在eax中 做完整的程序 这是我的代码:这里的问题是输入不起作用。如果我输入00,01,11-

  • 我就是无法让它工作。想法是设计一种方法,将键值对添加到Map,尽管程序编译正确,但测试格式为“tracker.put”(“17/06/2019”,“Jeffrey Burns”)的代码;“显示错误消息 我尝试将方法参数更改为(String, List)。 我期望测试代码跟踪器。put(“2019年6月17日”,“Jeffrey Burns”);但改为获取“错误:第1行-找不到符号-方法put(ja