分享

hive 下实现连续日期输出

各位大神现有一个问题,麻烦大家帮忙写个hql解决下,需求如下:源表T(两个字段)
monthid       cnt
20180101    101
20180102    102
20180103    100
20180105    104
20180107    105
20180108    102
20180109    103

输出:
monthid       cnt
20180101    101
20180102    102
20180103    100
20180104    0
20180105    104
20180106    0
20180107    105
20180108    102
20180109    103
也就是说希望输出每天的一个明细,如果当天没有cnt就输出0,思路是用T去左关联一个连续日期结果集,做case when处理如果monthid为空则赋值0,可能我的思路不正确,请大声指点,如果思路正确,请帮忙实现下,谢谢

已有(7)人评论

跳转到指定楼层
s060403072 发表于 2018-7-4 15:32:46
可以先链接表
monthid       cnt
20180101    101
20180102    102
20180103    100
20180104    null
20180105    104
20180106    null
20180107    105
20180108    102
20180109    103
相信表链接,应该是没有问题的。

我们在看下面内容:
select 字段1, 字段2,      
    case 字段3     
    when 值1 then 新值      
    when 值2 then 新值      
    end as 重新命名字段3的名字      
from table      
where

根据上面知识:

[mw_shl_code=sql,true]select  case monthid   
  
    when null then 0      

    end as monthid,cnt   

from table      

where .....[/mw_shl_code]






回复

使用道具 举报

BB_BDATA 发表于 2018-7-4 15:49:01
s060403072 发表于 2018-7-4 15:32
可以先链接表
monthid       cnt
20180101    101

那这个连续日期怎么实现呢?我源表数据日期是不连续的
回复

使用道具 举报

s060403072 发表于 2018-7-4 15:53:06
BB_BDATA 发表于 2018-7-4 15:49
那这个连续日期怎么实现呢?我源表数据日期是不连续的

你这个按理来说是必须要有的。但是奇怪的是并没有,既然没有,那就想法让他有呗。1.要么自己插入去
2.要么像楼主说的链接一个日期集。


回复

使用道具 举报

BB_BDATA 发表于 2018-7-4 15:58:08
s060403072 发表于 2018-7-4 15:53
你这个按理来说是必须要有的。但是奇怪的是并没有,既然没有,那就想法让他有呗。1.要么自己插入去
2.要 ...

嗯谢谢,手动插入,这个先不考虑了,主要是想知道怎么通过hql实现
回复

使用道具 举报

BB_BDATA 发表于 2018-7-25 17:49:04
本帖最后由 BB_BDATA 于 2018-7-25 17:56 编辑

自己写了个连续日期udf函数running_dates,部署后,通过查询源表src_test_1 中最小日期,最大日期,获取之间的连续日期结果集,在通过左关联实现:
select g.monthid,
       if(w.monthid is null, 0, w.cnt)
  from (select regexp_replace(k.monthid, '-', '') as monthid
          from (select explode(split(running_dates(
          min(from_unixtime(unix_timestamp(a.monthid,'yyyyMMdd'), 'yyyy-MM-dd')),
          max(from_unixtime(unix_timestamp(a.monthid,'yyyyMMdd'), 'yyyy-MM-dd'))),
                                     ',')) as monthid from src_test_1 a) k) g
  left join src_test_1 w on w.monthid = g.monthid;
结果如下:
20180101        101
20180102        102
20180103        100
20180104        0
20180105        104
20180106        0
20180107        105
20180108        102
20180109        103
回复

使用道具 举报

BB_BDATA 发表于 2018-7-25 17:53:07
本帖最后由 BB_BDATA 于 2018-7-25 17:54 编辑

package com.gml.functions.date;

import java.util.ArrayList;

import org.apache.hadoop.hive.ql.exec.Description;
import org.apache.hadoop.hive.ql.exec.UDF;
import org.apache.hadoop.io.Text;
import org.joda.time.LocalDate;
import org.joda.time.Period;
import org.joda.time.PeriodType;
import org.joda.time.format.DateTimeFormat;
import org.joda.time.format.DateTimeFormatter;

/**
* @author mingliang.ge
* @date 18-7-25
*/
@Description(name = "running_dates"
        , value = "_FUNC_(date1,date2) - return a running dates list from date1 to date2 with a singer format like yyyy-mm-dd."
        , extended = "Example:\n > select _FUNC_(date1_string,date2_string) from src;")
public class RunningDates extends UDF {
    public final static DateTimeFormatter DEFAULT_DATE_FORMATTER = DateTimeFormat.forPattern("yyyy-MM-dd");
    public final static DateTimeFormatter OUT_DATE_FORMATTER = DateTimeFormat.forPattern("yyyyMMdd");
    private Text result = new Text();
    private ArrayList<String> rs = new ArrayList<String>();

    public RunningDates() {

    }

    public Text evaluate(Text dateString1,Text dateString2) {
        if (dateString1 == null || dateString2 == null) {
            return null;
        }
        try {
            LocalDate date1 = LocalDate.parse(dateString1.toString(), DEFAULT_DATE_FORMATTER);
            LocalDate date2 = LocalDate.parse(dateString2.toString(), DEFAULT_DATE_FORMATTER);
            
            Period p = new Period(date1,date2,PeriodType.days());
            int diff=p.getDays();
            for(int i=0;i<=diff;i++){
                rs.add(date1.plusDays(i).toString(OUT_DATE_FORMATTER));
            }
            result.set(String.join(",", rs));
            return result;
        } catch (Exception e) {
            return null;
        }
    }
}

UDF函数代码附上,时间有限,尚有些弊端,例如:输入函数必须是yyyy-mm-dd格式才能识别由于源表数据时间格式为yyyymmdd,而且我们hive下一般时间存储都是yyyymmdd所以输出也是采用的这个格式
回复

使用道具 举报

BB_BDATA 发表于 2018-7-30 14:03:40
附件为UDF包,可以在hive下添加函数,方式如下:create temporary function running_dates as 'com.gml.functions.date.RunningDates';

hive-udf-gml-0.1.1-shaded.rar

89 Bytes, 下载次数: 12

回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条