maxcompute根据起始时间,生成时间段多行日期数据

具体需求是这样,有一张旅馆住宿表,表内有入住时间、离店时间等字段,现需要根据入住时间与离店时间生成入住期间的房晚数据。

 

PS:实验环境为maxcompute,hive的同学请自行调整  (杂乱的命名请忽略= =)

 

住宿测试表(test_get_dates):

数据:

需要生产的房晚数据:

 

在大佬的鞭策下一共想了两种实现方案:

(一)生成一张日期码表,并使用mapjoin的不等值关联

  1、创建时间码表dim_dates,如图

(id可以省略)

 

 2、使用mapjoin关联码表生成所需数据

select /*+MAPJOIN(a) */
a.times,
b.rzsj,
b.tfsj,
COALESCE(b.tfsj,b.rzsj) as bftfrq, --关联使用的住房日期
b.sfzhm
from dim_dates a
join test_get_dates b
on  a.times>=TO_DATE(to_char(b.rzsj,'yyyy-mm-dd'),'yyyy-mm-dd') and a.times< TO_DATE(to_char(b.tfsj,'yyyy-mm-dd'),'yyyy-mm-dd')  

 

查询结果如下

 

(二)编写UDTF,返回多行日期数据

1、编写UDTF,代码如下

import com.aliyun.odps.udf.UDTF;
import com.aliyun.odps.udf.annotation.Resolve;

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

@Resolve({"datetime,datetime,string,string->datetime,string,string,datetime,datetime"})
public class GetDatesUDTF extends UDTF {
    /**
     * @param args rzrq,tfrq,dwd_zjid,zjhm
     *             args[0] 入住日期
     *             args[1] 退房日期
     *             args[2] dwdid
     *             args[3] 身份证号码
     * @return 房晚日期,dwdid,身份证号码,入住时间,退房时间
     */
    @Override
    public void process(Object[] args) {
        Date bDate = (Date) args[0]; //获取入住时间
        Date eDate = (Date) args[1]; //获取退房时间
        Date bfDate = formateDate(bDate);
        Date efDate = formateDate(bDate!=null&&eDate==null?bDate:eDate);
        String dwdId = (String) args[2];
        String sfzhm = (String) args[3];
        if (bDate != null && efDate != null) {
            int days = getDateDiff(bfDate, efDate);
            try {
                Date d;
                for (int i = 0; i < days; i++) {
                    d = formateDate(getAddDate(bfDate,i));
                    forward(d, dwdId,sfzhm,bDate,eDate);
                }
            } catch (Exception e) {
                e.printStackTrace();
            }
        }

    }

    public Date getAddDate(Date date,int days){
        Calendar calendar = new GregorianCalendar();
        calendar.setTime(formateDate(date));
        calendar.add(Calendar.DAY_OF_MONTH, days);
        return calendar.getTime();
    }

    public Date formateDate(Date date) {
        if (date != null) {
            try {
                SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd");
                String fdateStr = sdf.format(date);
                date = sdf.parse(fdateStr);
                return date;
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

    public Date getEndDate(Date sdate, Date edate) {
        if (sdate != null && edate == null) {
           return formateDate(sdate);
        }
        return edate;
    }

    public int getDateDiff(Date sdate, Date edate) {
        long days = (edate.getTime() - sdate.getTime()) / (1000 * 60 * 60 * 24);
        return new Long(days).intValue();
    }
}

2、打包上传至maxcompute、创建函数getdates

 

3、使用UDTF

 

转载于:https://www.cnblogs.com/zzzmublog/p/11098710.html

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值