2014-12-19 3 views
0

나는 하이브에있는 함수를 찾고 있는데, 그 달에 날짜가 추가됩니다. 예를 들어하이브 기능 : 달 추가 날짜

:

add_month ('2014년 1월 1일', 1) -> '2014년 2월 1일'

add_month ('2013년 12월 1일', 1) -> '2014-01-01'

+0

1 월 31 일에 1 개월을 추가하면 어떻게됩니까? – Mike

+0

내 상황이 더 간단합니다. 예를 들어, 항상 첫 달에 1 개월을 추가해야합니다 (예 : 2014-01-01 -> 2014-02-01; 2013-12-01 -> 2014-01-01 – Marta

+0

표준 SQL에서이 날짜는 'date'2014-01-01 '+ interval'1 'month'입니다. Hive가 SQL 표준을 지원하는지 여부는 알 수 없습니다. –

답변

0

일반 UDF (GenericUDF)를 만들 수 있습니다. 당신이 좋아하는 기능을 사용할 수 있습니다

import static org.hamcrest.CoreMatchers.is; 
import static org.junit.Assert.assertNull; 
import static org.junit.Assert.assertThat; 

import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredJavaObject; 
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF.DeferredObject; 
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; 
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; 
import org.junit.Test; 

public class AddMonthTest { 
    private final String TEST_DATA = "2014-01-01"; 
    private final AddMonth addMonth = new AddMonth(); 
    ObjectInspector ob = PrimitiveObjectInspectorFactory.javaStringObjectInspector; 
    ObjectInspector ob1 = PrimitiveObjectInspectorFactory.javaIntObjectInspector; 
    private final ObjectInspector[]arg = { ob, ob1 }; 

    @Test 
    public void testAdd1Month() throws Exception { 
     DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA); 
     DeferredJavaObject def2 = new DeferredJavaObject(1); 

     addMonth.initialize(arg); 

     DeferredObject[] def = { def1, def2 }; 
     String resultData = addMonth.evaluate(def).toString(); 
     assertThat(resultData, is("2014-02-01")); 
    } 

    @Test 
    public void testAdd12Month() throws Exception { 
     DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA); 
     DeferredJavaObject def2 = new DeferredJavaObject(12); 

     addMonth.initialize(arg); 

     DeferredObject[] def = { def1, def2 }; 
     String resultData = addMonth.evaluate(def).toString(); 
     assertThat(resultData, is("2015-01-01")); 
    } 

    @Test 
    public void testSub1Month() throws Exception { 
     DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA); 
     DeferredJavaObject def2 = new DeferredJavaObject(-1); 

     addMonth.initialize(arg); 

     DeferredObject[] def = { def1, def2 }; 
     String resultData = addMonth.evaluate(def).toString(); 
     assertThat(resultData, is("2013-12-01")); 
    } 

    @Test 
    public void testSub12Month() throws Exception { 
     DeferredJavaObject def1 = new DeferredJavaObject(TEST_DATA); 
     DeferredJavaObject def2 = new DeferredJavaObject(-12); 

     addMonth.initialize(arg); 

     DeferredObject[] def = { def1, def2 }; 
     String resultData = addMonth.evaluate(def).toString(); 
     assertThat(resultData, is("2013-01-01")); 
    } 

    @Test 
    public void incorrectInput() throws Exception { 
     DeferredJavaObject def1 = new DeferredJavaObject("InvalidString"); 
     DeferredJavaObject def2 = new DeferredJavaObject(12); 

     addMonth.initialize(arg); 

     DeferredObject[] def = { def1, def2 }; 
     Object resultData = addMonth.evaluate(def); 
     assertNull(resultData); 
    } 
} 

:

import org.apache.hadoop.hive.ql.exec.UDFArgumentException; 
import org.apache.hadoop.hive.ql.exec.UDFArgumentLengthException; 
import org.apache.hadoop.hive.ql.metadata.HiveException; 
import org.apache.hadoop.hive.ql.udf.generic.GenericUDF; 
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspector; 
import org.apache.hadoop.hive.serde2.objectinspector.ObjectInspectorUtils; 
import org.apache.hadoop.hive.serde2.objectinspector.primitive.IntObjectInspector; 
import org.apache.hadoop.hive.serde2.objectinspector.primitive.PrimitiveObjectInspectorFactory; 
import org.apache.hadoop.hive.serde2.objectinspector.primitive.StringObjectInspector; 
import org.joda.time.LocalDate; 
import org.joda.time.format.DateTimeFormat; 
import org.apache.hadoop.io.IntWritable; 
import org.apache.hadoop.io.Text; 

public class AddMonth extends GenericUDF { 

    @Override 
    public ObjectInspector initialize(ObjectInspector[] arguments) throws UDFArgumentException { 
     if (arguments.length != 2) { 
      throw new UDFArgumentLengthException("The function add_month(local_date, months_to_add) requires 2 arguments."); 
     } 

     ObjectInspector localDateVal = arguments[0]; 
     ObjectInspector monthsToAddVal = arguments[1]; 

     if (!(localDateVal instanceof StringObjectInspector)) { 
      throw new UDFArgumentException("First argument must be of type String (local_date as String)"); 
     } 
     if (!(monthsToAddVal instanceof IntObjectInspector)) { 
      throw new UDFArgumentException("Second argument must be of type int (Month to add)"); 
     } 
     return PrimitiveObjectInspectorFactory.writableStringObjectInspector; 
    } 

    @Override 
    public Object evaluate(DeferredObject[] arguments) throws HiveException { 
     String localDateVal = (String) ObjectInspectorUtils.copyToStandardJavaObject(arguments[0].get(), 
       PrimitiveObjectInspectorFactory.javaStringObjectInspector); 
     IntWritable monthsToAddVal = (IntWritable) ObjectInspectorUtils.copyToStandardJavaObject(arguments[1].get(), 
       PrimitiveObjectInspectorFactory.javaIntObjectInspector); 

     LocalDate localDate = null; 
     try { 
      localDate = LocalDate.parse(localDateVal, DateTimeFormat.forPattern("yyyy-MM-dd")); 
     } catch (Exception ex) { 
      return null; 
     } 

     return new Text(localDate.plusMonths(monthsToAddVal.get().toString()); 
    } 

    @Override 
    public String getDisplayString(String[] arguments) { 
     assert (arguments.length == 2); 
     return "add_month(" + arguments[0] + ", " + arguments[1] + ")"; 
    } 
} 

테스트 케이스가 정확성을 입증하기 : 여기

은 샘플 UDF입니다

CREATE TEMPORARY FUNCTION add_month AS 'AddMonth'; 

SELECT 
    add_month ('2014-01-01',1) 
FROM 
    TAB_NAME; 

예상 출력 될 것입니다 :

2014-02-01 
+0

Text 및 writableInt로 전송할 때 오류가 계속 발생합니다. 어떤 힌트? – user3874377

+0

@ user3874377 코드 및 스택 추적을 게시하십시오. – Ambrish

+0

add_months를 사용할 수 있습니다. 다음을 참조하십시오. https://stackoverflow.com/questions/38221393/how-to-subtract-months-from-date-in-hive –