求连续登陆的用户日期

guid01,2018-02-28
guid01,2018-03-01
guid01,2018-03-02
guid01,2018-03-04
guid01,2018-03-05
guid01,2018-03-06
guid01,2018-03-07
guid02,2018-03-01
guid02,2018-03-02
guid02,2018-03-03
guid02,2018-03-06
 //第一个参数就传true或false因为以后有可能在本地执行,有可能提交到集群里面
    val islocal = args(0).toBoolean
    //这个主要作用是获取对象
    val conf = new SparkConf().setAppName(this.getClass.getCanonicalName)

    //通过if判断是local模式运行吗
    if(islocal){  //判断是否是本地运行模式,如果是则走本地运行
      conf.setMaster("local[*]")
    }
    //以后指定从哪里读取数据创建RDD
    val sc: SparkContext = new SparkContext(conf)

    //以后指定从哪里读取数据创建RDD,以后通过参数把他传进来
    val lines: RDD[String] = sc.textFile(args(1))

    //对数据进行整理
    val uidAndDate: RDD[(String, String)] = lines.map(line => {
      val fields = line.split(",") //先用逗号切分
      val uid = fields(0)  //把Uid存到 0 号区
      val date = fields(1)  //存到1号区
      (uid, date)  //然后把uid和date放到一起
    })
    //根据uid进行分组,将同一个用户的登录数据搞到同一个组内
    //注意对于k-v类型调用groupByKey最好
    val grouped: RDD[(String, Iterable[String])] = uidAndDate.groupByKey()

    //在组内的value值进行排序
    val uidAndDateDiff: RDD[(String, (String, String))] = grouped.flatMapValues(it => { //把value压平,再把key合在一起
      //将迭代器中的数据toList/toSet ,由于可能会出现某个用户每一天会多次登录,所以必须要先对日期去重,然后再转成列表
      //在对列表进行排序
      val sorted: List[String] = it.toSet.toList.sorted
      //定义一个日期类工具,表示可以对日期进行操作
      val calendar = Calendar.getInstance()
      //创建个日期形式
      val sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
      var index = 0
      sorted.map(dateStr => {
        val date: Date = sdf.parse(dateStr) //转成sdf定义的日期格式,本来是日期格式然后转换成date格式
        calendar.setTime(date)  //启动修改时间的机制
        calendar.add(Calendar.DATE, -index)
        index += 1
        //dateStr是指原来的时间,第二个参数是把当前时间拿出来
        (dateStr, sdf.format(calendar.getTime))
      })
    })

   /* val res: Array[(String, (String, String))] = uidAndDateDiff.collect()
    println(res.toBuffer)
    sc.stop()*/
    //(guid01,(2018-03-04,2018-03-01))

    val result1: RDD[((String, String), Iterable[String])] = uidAndDateDiff.map(t => {
      //参数1 key值,也就是uid t._2._2 表示被减去之后的日期,
      ((t._1, t._2._2), t._2._1) //表示登录的日期
      //按照key进行分组,查看组内有几条数据
    }).groupByKey()
    //对value进行操作
    val result2: RDD[(String, Int, String, String)] = result1.mapValues(it => {
      val list: List[String] = it.toList
      val times = list.size
      //怎样才能拿出一个起始时间,和一个结束时间呢
      val beginTime: String = list.head
      val endTime: String = list.last
      (times, beginTime, endTime)

    }).map(t => {
      //用户ID,连续多少天,起始时间,结束时间,
      (t._1._1, t._2._1, t._2._2, t._2._3)
    })
    println(result2.collect().toBuffer)
    sc.stop()

 

    //第一个参数传入true或false,因为后面肯能会在本地或者集群中运行
    val isLocal: Boolean = args(0).toBoolean
    //这个主要作用是获取对象
    val conf: SparkConf = new SparkConf().setAppName(this.getClass.getCanonicalName)

    //通过if判断是否在本地运行,一般在做测试的时候,是在本地运行
    if(isLocal){
      conf.setMaster("local[*]")
    }

    //指定以后在哪里读取数据
    val sc = new SparkContext(conf)

    //当读取数据完后,以后通过参数把他传进来,这样是一行一行的读取
    val lines: RDD[String] = sc.textFile(args(1))

    //对数据进行整理
    val uidAndDate: RDD[(String, String)] = lines.map(line => {
      //切割数据
      val fields: Array[String] = line.split(",")
      //把数据存储到相应的数组里面
      val uid: String = fields(0) //存放uid
      val date: String = fields(1) //存放日期,注意这些都是string类型
      (uid, date)
    })
    //现在对uid和日期进行处理并存放在数组里面,现在如何对日期进行处理
    //先对他按照key进行分组聚合
    val grouped: RDD[(String, Iterable[String])] = uidAndDate.groupByKey()
    /*val result: mutable.Buffer[(String, Iterable[String])] = grouped.collect().toBuffer
    println(result)
    //(guid01,CompactBuffer(2018-02-28, 2018-03-01, 2018-03-02, 2018-03-04, 2018-03-05, 2018-03-06, 2018-03-07))*/

    val uidAndDateDiff: RDD[(String, (String, String))] = grouped.flatMapValues(t => { //让每一个value值与key合在一起
      //先对value里面的元素进行操作
      val sorted: List[String] = t.toSet.toList.sorted
      //定义一个日期工具类,后面可对日期进行操作
      val calendar: Calendar = Calendar.getInstance()
      //创建一个日期格式,把日期进行格式化
      val sdf: SimpleDateFormat = new SimpleDateFormat("yyyy-MM-dd")
      var index = 0
      sorted.map(dateStr => {
        //把string类型格式的日期转成格式化类型
        val date = sdf.parse(dateStr)
        //把设置好的日期放到Calendar里面
        calendar.setTime(date)
        calendar.add(Calendar.DATE, -index)
        index += 1
        (dateStr, sdf.format(calendar.getTime)) //获取当前时间
      })
    })
    //在完成分组聚合之后再对value  map一下  (guid01,2018-02-28), (guid01,2018-03-01),
   // val result1: Array[(String, (String, String))] = uidAndDateDiff.collect()
   // println(result1.toBuffer)
    //guid01,(2018-02-28,2018-02-28))


    val result1: RDD[((String, String), String)] = uidAndDateDiff.map(t => {
      ((t._1, t._2._2), t._2._1) //显示uid,被减去之后的日期,和初始登录日期

    })
    val res: RDD[((String, String), Iterable[String])] = result1.groupByKey()
    //val tuples: Array[((String, String), Iterable[String])] = res.collect()
   // println(tuples.toBuffer)
  //((guid02,2018-03-01),CompactBuffer(2018-03-01, 2018-03-02, 2018-03-03))

    //继续操作
    val res2: RDD[((String, String), (Int, String, String))] = res.mapValues(t => { //注意着仅仅只是对value进行处理
      //先把整个元组转成列表的形式
      val list: List[String] = t.toList
      val times: Int = list.size
      val beginTime: String = list.head
      val lastTime: String = list.last
      (times, beginTime, lastTime)
    })
    val res3: RDD[(String, Int, String, String)] = res2.map(t => {
      (t._1._1, t._2._1, t._2._2, t._2._3)
    })
    println(res3.collect().toBuffer)
    sc.stop()
    //(guid02,3,2018-03-01,2018-03-03)

 

 

### 回答1: 在 MySQL 中,可以使用以下语句来实现统计连续三天登录用户: ``` SELECT user_id FROM login_history WHERE login_time BETWEEN DATE_SUB(NOW(), INTERVAL 3 DAY) AND NOW() GROUP BY user_id HAVING COUNT(*) = 3 ``` 这条查询会搜索在过去三天内的所有登录记录,然后分组每个用户登录记录,最后筛选出登录记录数量等于 3 的用户。 假设你有一张名为 `login_history` 的表,其中包含了登录记录,表结构如下: ``` +---------+------------+ | user_id | login_time | +---------+------------+ | 1 | 2021-01-01 | | 1 | 2021-01-02 | | 1 | 2021-01-03 | | 2 | 2021-01-01 | | 2 | 2021-01-02 | | 3 | 2021-01-01 | | 3 | 2021-01-03 | +---------+------------+ ``` 执行上面的查询后,结果为: ``` +---------+ | user_id | +---------+ | 1 | +---------+ ``` 可以看到,用户 1 在过去三天内都登录了,所以被选中。其他用户未被选中,是因为他们在过去三天内有一天没有登录。 ### 回答2: 要实现统计连续三天登录用户,可以通过以下步骤: 1. 首先,创建一个包含用户登录信息的表,可以包括用户ID登录日期字段。例如,创建一个名为 "login_info" 的表,包含 "user_id" 和 "login_date" 字段。 2. 使用MySQL的时间函数和日期函数来确保只获取最近三天内的登录日期。可以使用CURDATE()获取当前日期,使用DATE_SUB()和INTERVAL来计算三天前的日期。在查询语句中,使用WHERE子句来筛选出在这个日期范围内的登录记录。 3. 使用GROUP BY子句按照用户ID进行分组,以便根据用户进行统计。 4. 使用HAVING子句来筛选出连续三天登录用户。在这个例子中,使用COUNT(*)函数来计算每个用户登录次数,然后使用条件语句COUNT(*)=3来筛选出登录次数为3的用户,即连续三天登录。 以下是一个示例查询语句的示例: SELECT user_id FROM login_info WHERE login_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) -- 最近三天内的登录日期 GROUP BY user_id HAVING COUNT(*) = 3; -- 登录次数为3即连续三天登录 这样,就可以通过以上步骤来实现统计连续三天登录用户。 ### 回答3: 要实现统计连续三天登陆用户,可以使用MySQL数据库的日期函数和子查询来实现。 首先,假设用户登录信息存储在一个表中,包含用户ID(user_id)和登录日期(login_date)两个字段。 可以使用DATE_SUB函数和CURDATE函数结合,查询连续三天的登录记录。具体的SQL查询语句如下: ``` SELECT user_id FROM login_records WHERE login_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY) GROUP BY user_id HAVING COUNT(DISTINCT login_date) = 3; ``` 解释一下以上查询语句的步骤: 1. `DATE_SUB(CURDATE(), INTERVAL 2 DAY)`用于获取当前日期的前两天日期。 2. `WHERE login_date >= DATE_SUB(CURDATE(), INTERVAL 2 DAY)`筛选出登录日期连续三天之内的记录。 3. `GROUP BY user_id`按用户ID进行分组。 4. `HAVING COUNT(DISTINCT login_date) = 3`根据分组后的用户ID,统计不重复的登录日期数量为3。 以上查询语句会返回所有连续三天登陆用户ID列表。 需要注意的是,以上的查询语句只能统计连续三天登录用户,如果要统计连续N天登录用户,只需将查询语句中的数字2改为N-1即可。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值