一段时间内的所有日期

3 篇文章 0 订阅

背景: 求活动实际进行天数

一品牌进行多场营销活动,多场活动起止时间上有重合,求该品牌进行活动的天数,如果活动时间有重复,只能算一次 。
使用工具是: hive sql

表结构及假数据

  1. 表结构是:
create table if not exists tmp_marketing (
  brand string comment '品牌',
  startdate string comment '开始时间',
  enddate string comment '结束时间'
) comment '品牌活动时间记录';
  1. 表中假数据:
brandstartdateenddate
苹果2018-09-012018-09-05
苹果2018-09-032018-09-06
苹果2018-09-092018-09-15
mi2018-09-092018-09-15
mi2018-09-012018-09-05
mi2018-09-062018-09-08
  1. 想要达到的效果
brand天数
mi15
苹果13

方法一

先上代码,配上注释,自行服用哦 ~

with grp_starts as ( -- 该条记录时间与上一条记录对比,标记是否有重复日期
  select brand, startdate, enddate,
  case when startdate > max(enddate) over( partition by brand order by startdate, enddate rows between unbounded preceding and 1 preceding ) 
  then 1 else 0 end grp_start
  from tmp_marketing
)
, grps as (--将有重复部分进行聚合
  select brand, startdate, enddate,
  sum(grp_start) over( partition by brand order by startdate, enddate
    rows between unbounded preceding and current row
  ) grp
  from grp_starts
)
select --按照品牌聚合,天数, 得到结果
brand
,sum(diffdates) as `天数`
from
(--得到有重合部分的最小开始时间和最大结束时间,算出时间差,就是活动跨天数
select brand,grp,
min(startdate) start_date,
max(enddate) end_date,
datediff(max(enddate),min(startdate)) +1 as diffdates
from grps
group by brand, grp)
group by brand;

引子

看到本文标题, 就知道方法一,并不是结束, 那么如果知道每个活动的起止时间经历的所有日期, 去重之后,直接聚合, 不是快速且愉快的得到所需结果, 那么有没有这样的函数呢? 扭头,看到了 sequence
来看看这个用法:

SELECT sequence(start_dt, end_dt, INTERVAL 1 DAY) AS date_list
FROM (SELECT date('2021-01-01') AS start_dt, date('2021-01-05') AS end_dt) date_range
date_list
[2021-01-01, 2021-01-02, 2021-01-03, 2021-01-04, 2021-01-05]

方法二

一样的, show code ,配上注释,自行服用哦 ~

SELECT --聚合每个品牌的营销天数
brand
,count(1) as  `天数`
FROM
(SELECT --爆炸函数,得到每个活动的起止时间经历的所有日期,并且去重
brand
,dt
FROM (SELECT
    brand
    ,date(startdate) AS start_dt
    ,date(enddate) AS end_dt 
    from tmp_marketing ) date_range
LATERAL VIEW EXPLODE(sequence(start_dt, end_dt)) date_view AS dt
GROUP BY brand
,dt ) tt
GROUP BY brand

以上.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值