<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Hive實(shí)戰(zhàn)—時(shí)間滑動(dòng)窗口計(jì)算

          共 683字,需瀏覽 2分鐘

           ·

          2021-12-24 21:50

          關(guān)注公眾號(hào):大數(shù)據(jù)技術(shù)派,回復(fù)資料,領(lǐng)取1024G資料。

          • 時(shí)間滑動(dòng)計(jì)算

            • 外部調(diào)用實(shí)現(xiàn)時(shí)間循環(huán)

            • 自關(guān)聯(lián)實(shí)現(xiàn)滑動(dòng)時(shí)間窗口

            • 擴(kuò)展基于自然周的的滾動(dòng)時(shí)間窗口計(jì)算

          • 總結(jié)

          時(shí)間滑動(dòng)計(jì)算

          今天遇到一個(gè)需求大致是這樣的,我們有一個(gè)業(yè)務(wù)涉及到用戶打卡,用戶可以一天多次打卡,我們希望計(jì)算出7天內(nèi)打卡8次以上,且打卡時(shí)間分布在4天以上的時(shí)間,當(dāng)然這只是個(gè)例子,我們具體解釋一下這個(gè)需求

          1. 用戶一天可以打卡多次,所以要求打卡必須分布在4天以上;
          2. 7天不是一個(gè)自然周,而是某一天和接下來(lái)的6天,也就是說(shuō)時(shí)間是是滑動(dòng)的,窗口大小是7步長(zhǎng)是1,說(shuō)白了就是窗口計(jì)算;

          其實(shí)說(shuō)到這里你就想到了窗口函數(shù),雖然這是一個(gè)窗口;但是hive卻沒有相應(yīng)的窗口函數(shù)可以計(jì)算,接下來(lái)我們看一下怎么實(shí)現(xiàn)這個(gè)邏輯。

          外部調(diào)用實(shí)現(xiàn)時(shí)間循環(huán)

          我們可以先寫這樣的一個(gè)SQL,就計(jì)算每個(gè)人在特定時(shí)間內(nèi)是否滿足我們的條件,我們先計(jì)算出每個(gè)人每天的打卡次數(shù),例如這里我們的時(shí)間限制是'20210701' 到'20210707'

          ??select
          ?????b.union_id,to_date(ds,'yyyymmdd')?as?dt,count(1)?as?cnt
          ??from
          ????ods_la_daily_record_di?b
          ??where
          ????--?驅(qū)動(dòng)表的時(shí)間限制
          ????b.ds>='${bizdate}'
          ????and?b.ds<=${bizdate2}'
          ??group?by
          ????b.union_id,ds

          然后我們?cè)倥袛噙@個(gè)時(shí)間端內(nèi),用戶的打卡情況是否滿足我們的條件

          select
          ??union_id,count(1)?as?打卡天數(shù),?sum(cnt)?as?打卡次數(shù)
          from
          (
          ??select
          ?????b.union_id,ds,count(1)?as?cnt
          ??from
          ????ods_la_daily_record_di?b
          ??where
          ????--?驅(qū)動(dòng)表的時(shí)間限制
          ????b.ds>='${bizdate}'
          ????and?b.ds<='${bizdate2}'
          ??group?by
          ????b.union_id,ds
          )
          group?by
          ??union_id
          having
          ??--?時(shí)間分布在4天以上
          ??count(1)>=4
          ??--?打卡次數(shù)在8次以上
          ??and?sum(cnt)>=8
          ;

          這樣我們就算出來(lái)我們需要的數(shù)據(jù),接下來(lái)我們只需要用其他語(yǔ)言調(diào)用這個(gè)SQL ,傳入不同的時(shí)間參數(shù)就可以了,利用編程語(yǔ)言實(shí)現(xiàn)時(shí)間的滑動(dòng),例如第一次傳入'20210701-20210707' 第二次傳入'20210702-20210708' 以此傳入即可。

          雖然可以實(shí)現(xiàn),但是不好,因?yàn)槲覀冞€需要其他語(yǔ)言的調(diào)用,其實(shí)我們知道在SQL里面的關(guān)聯(lián)其實(shí)就是通過(guò)循環(huán)實(shí)現(xiàn)的,那我們即然能通過(guò)循環(huán)實(shí)現(xiàn)這個(gè)需求,我們能不能通過(guò)關(guān)聯(lián)實(shí)現(xiàn)這個(gè)需求呢

          自關(guān)聯(lián)實(shí)現(xiàn)滑動(dòng)時(shí)間窗口

          其實(shí)我們只要讓用戶某一天的數(shù)據(jù)和他接下來(lái)的6天的數(shù)據(jù)關(guān)聯(lián),然后按照這一天的數(shù)據(jù)進(jìn)行匯總?cè)缓笈袛鄷r(shí)候滿足我們的條件即可,如果滿足了條件,那么用戶這一天的數(shù)據(jù)就是滿足我們的需求的,也就是說(shuō)這個(gè)用戶是滿足我們的需求的。

          with?tmp?as(
          ???--?每個(gè)人每天打卡的次數(shù)
          ??select
          ?????b.union_id,to_date(ds,'yyyymmdd')?as?dt,count(1)?as?cnt
          ??from
          ????ods_la_daily_record_di?b
          ??where
          ????--?驅(qū)動(dòng)表的時(shí)間限制
          ????b.ds>='${bizdate}'
          ??group?by
          ????b.union_id,ds
          )
          select
          ??union_id
          from?(
          ??--?滿足條件的(用戶-天)
          ??select
          ????a.union_id,a.dt,sum(b.cnt)?as?打卡次數(shù),count(1)?as?打卡天數(shù)
          ??from
          ????tmp?a
          ??inner?join
          ???tmp?b
          ??on
          ????a.union_id=b.union_id
          ????and?DATEDIFF(b.dt,a.dt)>=0
          ????and?DATEDIFF(b.dt,a.dt)<=6
          ??group?by
          ????a.union_id,a.dt
          ??having
          ????--?次數(shù)限制
          ????sum(b.cnt)>=8
          ????--?天數(shù)限制
          ????and?count(1)>=4
          )group?by
          ??--?對(duì)用戶去重
          ??union_id
          ;

          這里有一個(gè)問題需要注意一下,那就是我們滿足條件sum(b.cnt)>=8 and count(1)>=4 的是用戶某一天的數(shù)據(jù),也就是說(shuō)我們的維度是union_id-天,所以我們需要對(duì)這個(gè)數(shù)據(jù)按照用戶為度進(jìn)行去重。

          擴(kuò)展基于自然周的的滾動(dòng)時(shí)間窗口計(jì)算

          我們這里思考一個(gè)問題,那就是我們知道很多時(shí)候我們的計(jì)算其實(shí)是圍繞著自然周的,雖然我們上面的計(jì)算不是自然周,那假設(shè)我們?nèi)绻笪覀兊挠?jì)算是自然周呢,那這個(gè)時(shí)候我們應(yīng)該怎么計(jì)算呢,其實(shí)我們數(shù)倉(cāng)里有一種很表叫做時(shí)間維表,我們利用時(shí)間維表可以很方便的計(jì)算時(shí)間相關(guān)的東西,如果你沒有的話建議去網(wǎng)上找一份,或者自己生成一份,因?yàn)槭褂闷饋?lái)很方便。

          因?yàn)檫@個(gè)表的字段很多,這里我們截取了一部分放到這里了,下面我們看一下怎么使用時(shí)間維表進(jìn)行計(jì)算。

          select
          ???UNION_ID,time_weeknum,count(1)?as?打卡天數(shù),?sum(cnt)?as?打卡次數(shù)
          from(
          ??select
          ?????b.union_id,ds,count(1)?as?cnt
          ??from
          ????ods_la_daily_record_di?b
          ??where
          ????--?驅(qū)動(dòng)表的時(shí)間限制
          ????b.ds>='${bizdate}'
          ????and?b.ds<='${bizdate2}'
          ??group?by
          ????b.union_id,ds
          )?a
          left?join
          dim_date_time?b
          on
          ??a.ds=b.time_date
          group?by
          ??--??周的標(biāo)識(shí)
          ??UNION_ID,time_weeknum
          HAVING
          ??--?時(shí)間分布在4天以上
          ??count(1)>=4
          ??--?打卡次數(shù)在8次以上
          ??and?sum(cnt)>=8
          ;

          這里我們就基于每個(gè)自然周算出了滿足條件的人,當(dāng)然我們還是要針對(duì)用戶去重

          總結(jié)

          我們看到自關(guān)聯(lián)其實(shí)可以達(dá)到滑動(dòng)的效果,當(dāng)然不僅僅體現(xiàn)在時(shí)間上,就像窗口除了時(shí)間窗口還是有基于個(gè)數(shù)的窗口,我們要在遇到類似問題的時(shí)候就可以選擇這樣的解決方案。

          時(shí)間維表很重要,可以簡(jiǎn)化我們的計(jì)算,如果沒有的話,需要?jiǎng)?chuàng)建一個(gè)。

          交流群

          加我微信:ddxygq,回復(fù)加群,我拉你進(jìn)技術(shù)交流群。

          猜你喜歡
          數(shù)倉(cāng)建?!笜?biāo)體系
          數(shù)倉(cāng)建?!獙挶淼脑O(shè)計(jì)
          Spark SQL知識(shí)點(diǎn)與實(shí)戰(zhàn)
          Hive計(jì)算最大連續(xù)登陸天數(shù)
          Flink計(jì)算pv和uv的通用方法

          瀏覽 40
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  777久久婷婷成人综合色 | 国产黄片在线播放 | 韩国一级一级免费 | 韩国成人电影一区二区三区 | 91传媒在线观看网站 |