最新国产好看的视频,伊人天堂AV在线,国产Aaaaaa视频,蜜臀视频在线观看一区,人妻av色图,密臀久久久精品影片,青青视频免费观看毛片,久草在线观看视,国产三级精品色情在线

Hive實(shí)現(xiàn)連續(xù)N天登陸語法實(shí)例代碼

 更新時(shí)間:2026年04月04日 08:54:09   作者:小小草臺班子  
在用戶行為數(shù)據(jù)分析中,常常需要分析用戶的連續(xù)登錄行為,下面這篇文章主要介紹了Hive實(shí)現(xiàn)連續(xù)N天登陸語法的相關(guān)資料,文中通過代碼介紹的非常詳細(xì),需要的朋友可以參考下

Sql方式實(shí)現(xiàn)連續(xù)N天登陸

構(gòu)造測試數(shù)據(jù)
create table dwd.login_log as
select 1 as user_id, "2020-01-01" as login_date
union all
select 1 as user_id, "2020-01-02" as login_date
union all
select 1 as user_id, "2020-01-07" as login_date
union all
select 1 as user_id, "2020-01-08" as login_date
union all
select 1 as user_id, "2020-01-09" as login_date
union all
select 1 as user_id, "2020-01-10" as login_date
union all
select 2 as user_id, "2020-01-01" as login_date
union all
select 2 as user_id, "2020-01-02" as login_date
union all
select 2 as user_id, "2020-01-04" as login_date

如果日期格式不規(guī)范,可以將其轉(zhuǎn)換為標(biāo)準(zhǔn)格式

create table dwd.login_log as
select user_id,to_date(from_unixtime(UNIX_TIMESTAMP(login_date,'yyyy-MM-dd'))) as login_date
from tmp.login_log; -- tmp庫為原始數(shù)據(jù)

1.使用lag&lead+datediff窗口函數(shù)

  • 比如求連續(xù)三天登陸,可以將當(dāng)天上一條數(shù)據(jù)和下一條數(shù)據(jù)都拿到,然后保證now-lag=lead-now=1即可;
  • 如果是連續(xù)多天,可以取更多的數(shù)據(jù),或者將數(shù)據(jù)全部更改為lag或者lead函數(shù);
  • datediff(date1, date2) - Returns the number of days between date1 and date2
select user_id 
from 
  (select user_id
  from
      (select user_id,
            lag(login_date,1) over(partition by user_id order by login_date) as lag_login_date,
            login_date,
            lead(login_date,1) over(partition by user_id order by login_date) as lead_login_date
      from dwd.login_log)t1
  where datediff(login_date,lag_login_date)=1 and datediff(lead_login_date,login_date)=1)t2
group by user_id;

2.使用date_add函數(shù)

  • 通用的,先對user_id分區(qū)排序,然后將日期減去rank天,查看有多少條數(shù)據(jù)即可;
  • 優(yōu)點(diǎn)在于可以統(tǒng)計(jì)具體連續(xù)登陸多少天,以及連續(xù)登陸的實(shí)際情況;
  • date_add(start_date, num_days) - Returns the date that is num_days after start_date
select user_id,con_login_date,count(*) nums
from
    (select user_id,login_date,rk,date_add(login_date,1 - rk) as con_login_date
    from 
        (select user_id,login_date,rank() over(partition by user_id order by login_date) rk
        from dwd.login_log)t1
    )t2
group by user_id,con_login_date
having count(*) >= 3;
  • t1表的查詢結(jié)果
用戶id登陸時(shí)間按照登陸時(shí)間組內(nèi)排序
12020-01-011
12020-01-022
12020-01-073
12020-01-084
12020-01-095
12020-01-106
22020-01-011
22020-01-022
22020-01-043
  • t2表的查詢結(jié)果,歸一化的日期(也就是上述取前1 - rk)可以自己定義
用戶id登陸時(shí)間連續(xù)登陸的日期歸一化的日期
12020-01-012020-01-01
12020-01-022020-01-01
12020-01-072020-01-05
12020-01-082020-01-05
12020-01-092020-01-05
12020-01-102020-01-05
22020-01-12020-01-01
22020-01-22020-01-01
22020-01-42020-01-02
  • group by后的查詢結(jié)果,第三列可以按照session內(nèi)統(tǒng)計(jì)來理解,就是這批連續(xù)登陸內(nèi)連續(xù)登陸的天數(shù)
用戶id連續(xù)登陸的日期歸一化的日期用戶此次連續(xù)登陸天數(shù)
12020-01-012
12020-01-054
22020-01-012
22020-01-021

代碼實(shí)現(xiàn)思路

  • 使用代碼來實(shí)現(xiàn)連續(xù)N天登陸,核心邏輯就是按照日期排序,新日期如果和舊日期相差1天就保留在HashMap里面,Size超過N即可輸出user_id,否則清空
package cn.lang.spark_core
import java.text.{ParseException, SimpleDateFormat}
import java.util.Calendar
import org.apache.spark.sql.SparkSession
object ContinuousLoginDays {
  def main(args: Array[String]): Unit = {
    // env
    val spark: SparkSession = SparkSession
      .builder()
      .appName("ContinuousLoginDays")
      .master("local[*]")
      .getOrCreate()
    val sc = spark.sparkContext
    // source,可以是load hive(開啟hive支持)或者parquet列式文件(定義好schema)
    val source = sc.textFile("/user/hive/warehouse/dwd/login_log")
    case class Login(uid: Int, loginTime: String) // 可以kryo序列化
    /** get date last `abs(n)` days defore or after biz_date   *
     * example biz_date = 20200101 ,last_n = 1,return 20191231 */
    def getLastNDate(biz_date: String,
                     date_format: String = "yyyyMMdd",
                     last_n: Int = 1): String = {
      val calendar: Calendar = Calendar.getInstance()
      val sdf = new SimpleDateFormat(date_format)
      try
        calendar.setTime(sdf.parse(biz_date))
      catch {
        case e: ParseException => // omit
      }
      calendar.set(Calendar.DATE, calendar.get(Calendar.DATE) - last_n)
      sdf.format(calendar.getTime)
    }
    // transform
    val result = source
      .map(_.split("\t"))
      .map(iterm => Login(iterm(0).toInt, iterm(1)))
      .groupBy(_.uid) // RDD[(Int, Iterable[Login])]
      .map(iterm => {
        // 用于給此uid標(biāo)記是否符合要求
        var CONTINUOUS_LOGIN_N = false
        val logins = iterm._2
          .toSeq
          .sortWith((v1, v2) => v1.loginTime.compareTo(v2.loginTime) > 0)
        var lastLoginTime: String = ""
        var loginDays: Int = 0
        logins
          .foreach(iterm => {
            if (lastLoginTime == "") {
              lastLoginTime = iterm.loginTime
              loginDays = 1
            } else if (getLastNDate(iterm.loginTime) == lastLoginTime) {
              lastLoginTime = iterm.loginTime
              loginDays = 2
            } else {
              lastLoginTime = iterm.loginTime
              loginDays = 1
            }
          })
        if (loginDays > 3) CONTINUOUS_LOGIN_N = true
        /** 此處可以使用集合將連續(xù)登陸的情況保留,
         * 也可以直接按照是否連續(xù)登陸N天進(jìn)行標(biāo)記
         */
        (iterm._1, CONTINUOUS_LOGIN_N)
      })
      .filter(_._2)
      .map(_._1)
    // sink
    result.foreach(println(_))
  }
}

總結(jié)

到此這篇關(guān)于Hive實(shí)現(xiàn)連續(xù)N天登陸語法的文章就介紹到這了,更多相關(guān)Hive連續(xù)N天登陸內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • 詳解IDEA中便捷內(nèi)存數(shù)據(jù)庫H2的最簡使用方式

    詳解IDEA中便捷內(nèi)存數(shù)據(jù)庫H2的最簡使用方式

    這篇文章主要介紹了詳解IDEA中便捷內(nèi)存數(shù)據(jù)庫H2的最簡使用方式,文中通過示例代碼介紹的非常詳細(xì),對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來一起學(xué)習(xí)學(xué)習(xí)吧
    2021-03-03
  • Kafka高效讀寫數(shù)據(jù)的原因及如何提升Kafka的吞吐量

    Kafka高效讀寫數(shù)據(jù)的原因及如何提升Kafka的吞吐量

    本文主要介紹了Kafka的高效讀寫數(shù)據(jù)的原因及如何提升Kafka的吞吐量,Kafka通過分區(qū)、稀疏索引等零拷貝等技術(shù)提高了讀寫效率,增加緩沖區(qū)大小、調(diào)整batch、linger等參數(shù)可以提升生產(chǎn)者端的吞吐量,調(diào)整fetch.max.size等max.poll.records等參數(shù)可以提升消費(fèi)者端的吞吐量
    2026-05-05
  • Navicat中修改MySQL的編碼格式

    Navicat中修改MySQL的編碼格式

    打開?Navicat?for?MySQL?并連接到您的數(shù)據(jù)庫服務(wù)器,在左側(cè)的連接列表中,展開數(shù)據(jù)庫,然后展開要更改字符集的表,選中要更改字符集的表,右鍵點(diǎn)擊并選擇?"設(shè)計(jì)表",在?"設(shè)計(jì)表"?窗口中,您將看到表的列表
    2023-10-10
  • db2數(shù)據(jù)庫常用操作命令大全

    db2數(shù)據(jù)庫常用操作命令大全

    這篇文章主要介紹了db2數(shù)據(jù)庫常用操作命令大全,匯總了DB2的常用操作命令,分享給大家供大家參考,需要的朋友可以參考下
    2014-09-09
  • 一個(gè)提升PostgreSQL性能的小技巧

    一個(gè)提升PostgreSQL性能的小技巧

    這篇文章主要介紹了一個(gè)提升Postgres性能的小技巧,通過修改很少的代碼來優(yōu)化查詢,需要的朋友可以參考下
    2015-04-04
  • 用計(jì)算列實(shí)現(xiàn)移動(dòng)加權(quán)平均算法

    用計(jì)算列實(shí)現(xiàn)移動(dòng)加權(quán)平均算法

    昨天有人讓我?guī)兔憘€(gè)算移動(dòng)加權(quán)平均的SQL語句,我想了半天終于寫出來正確的了?,F(xiàn)在發(fā)出來供大家參考、討論。
    2009-09-09
  • 數(shù)據(jù)庫加密字段進(jìn)行模糊查詢詳解

    數(shù)據(jù)庫加密字段進(jìn)行模糊查詢詳解

    這篇文章主要為大家介紹了數(shù)據(jù)庫加密字段進(jìn)行模糊查詢詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪
    2022-09-09
  • 詳解Navicat Premium基本使用

    詳解Navicat Premium基本使用

    Navicat是一套數(shù)據(jù)庫管理工具,專為簡化數(shù)據(jù)庫的管理及降低系統(tǒng)管理成本而設(shè)。這篇文章主要介紹了詳解Navicat Premium基本使用,需要的朋友可以參考下
    2020-11-11
  • 復(fù)制數(shù)據(jù)庫表中兩個(gè)字段數(shù)據(jù)的SQL語句

    復(fù)制數(shù)據(jù)庫表中兩個(gè)字段數(shù)據(jù)的SQL語句

    今天為表新添加一個(gè)字段,但又想與表中的另一個(gè)字段值相同,由于數(shù)據(jù)過多想通過sql語句實(shí)現(xiàn),經(jīng)測試下面的這句話確實(shí)很好用
    2013-07-07
  • Navicat恢復(fù)數(shù)據(jù)庫連接及查詢sql的完美解決辦法

    Navicat恢復(fù)數(shù)據(jù)庫連接及查詢sql的完美解決辦法

    因?yàn)楣窘o電腦加域,導(dǎo)致使用新的用戶賬戶,原先的很多配置都失效了,這篇文章主要介紹了Navicat恢復(fù)數(shù)據(jù)庫連接及查詢sql的解決辦法,需要的朋友可以參考下
    2023-08-08

最新評論

射阳县| 湟中县| 隆化县| 曲阜市| 滦平县| 阿拉善右旗| 吉安市| 雅江县| 普格县| 徐闻县| 上饶市| 黄陵县| 苏尼特右旗| 广德县| 太仓市| 云阳县| 庆安县| 仙游县| 资兴市| 长治市| 永州市| 宜城市| 镇原县| 吉隆县| 阳城县| 夏河县| 安吉县| 布尔津县| 龙山县| 东乡县| 治县。| 萍乡市| 茂名市| 郓城县| 西平县| 平乡县| 司法| 望都县| 都兰县| 新龙县| 景谷|