案例 统计用户上网流量,如果两次上网的时间小于10分钟,合并到一起 --SparkSql实现(SQL风格)

数据如下

+---+-------------------+-------------------+----+
| id|         start_time|           end_time|flow|
+---+-------------------+-------------------+----+
|  1|2020-02-18 14:20:30|2020-02-18 14:46:30|  20|
|  1|2020-02-18 14:47:20|2020-02-18 15:20:30|  30|
|  1|2020-02-18 15:37:23|2020-02-18 16:05:26|  40|
|  1|2020-02-18 16:06:27|2020-02-18 17:20:49|  50|
|  1|2020-02-18 17:21:50|2020-02-18 18:03:27|  60|
|  2|2020-02-18 14:18:24|2020-02-18 15:01:40|  20|
|  2|2020-02-18 15:20:49|2020-02-18 15:30:24|  30|
|  2|2020-02-18 16:01:23|2020-02-18 16:40:32|  40|
|  2|2020-02-18 16:44:56|2020-02-18 17:40:52|  50|
|  3|2020-02-18 14:39:58|2020-02-18 15:35:53|  20|
|  3|2020-02-18 15:36:39|2020-02-18 15:24:54|  30|
+---+-------------------+-------------------+----+
select
  uid,
  min(start_time) start_time,
  max(end_time) end_time,
  sum(flow) flow
from
(
  select
    uid,
    start_time,
    end_time,
    flow,
    sum(flag) over(partition by uid order by start_time) sum_flag
  from
  (
    select
      uid,
      start_time,
      end_time,
      flow,
      if((to_unix_timestamp(start_time) - to_unix_timestamp(lag_time))/60 > 10, 1,0) flag  -- 将日期转为时间戳,秒为单位
    from
     (
       select
         uid,
         start_time,
         end_time,
         flow,
         lag(end_time,1,start_time) over(partition by uid order by start_time) lag_time
       from
         tb_flowCount
     )
  )
)
group by uid,sum_flag

结果:

+---+-------------------+-------------------+---------+
|uid|         start_time|           end_time|     flow|
+---+-------------------+-------------------+---------+
|  1|2020-02-18 14:20:30|2020-02-18 15:20:30|       50|
|  1|2020-02-18 15:37:23|2020-02-18 18:03:27|      150|
|  3|2020-02-18 14:39:58|2020-02-18 15:35:53|       50|
|  2|2020-02-18 14:18:24|2020-02-18 15:01:40|       20|
|  2|2020-02-18 15:20:49|2020-02-18 15:30:24|       30|
|  2|2020-02-18 16:01:23|2020-02-18 17:40:52|       90|
+---+-------------------+-------------------+---------+

过程解析

1

select
    uid,
    start_time,
    end_time,
    flow,
    lag(end_time,1,start_time) over(partition by uid order by start_time) lag_time  --将上一行的结束时间压到下一行
from
    tb_flowCount

+---+-------------------+-------------------+----+----------------------+
|uid|         start_time|           end_time|flow|              lag_time|
+---+-------------------+-------------------+----+----------------------+
|  1|2020-02-18 14:20:30|2020-02-18 14:46:30|  20|   2020-02-18 14:20:30|
|  1|2020-02-18 14:47:20|2020-02-18 15:20:30|  30|   2020-02-18 14:46:30|
|  1|2020-02-18 15:37:23|2020-02-18 16:05:26|  40|   2020-02-18 15:20:30|
|  1|2020-02-18 16:06:27|2020-02-18 17:20:49|  50|   2020-02-18 16:05:26|
|  1|2020-02-18 17:21:50|2020-02-18 18:03:27|  60|   2020-02-18 17:20:49|
|  3|2020-02-18 14:39:58|2020-02-18 15:35:53|  20|   2020-02-18 14:39:58|
|  3|2020-02-18 15:36:39|2020-02-18 15:24:54|  30|   2020-02-18 15:35:53|
|  2|2020-02-18 14:18:24|2020-02-18 15:01:40|  20|   2020-02-18 14:18:24|
|  2|2020-02-18 15:20:49|2020-02-18 15:30:24|  30|   2020-02-18 15:01:40|
|  2|2020-02-18 16:01:23|2020-02-18 16:40:32|  40|   2020-02-18 15:30:24|
|  2|2020-02-18 16:44:56|2020-02-18 17:40:52|  50|   2020-02-18 16:40:32|
+---+-------------------+-------------------+----+----------------------+

2

select
  uid,
  start_time,
  end_time,
  flow,
  if((to_unix_timestamp(start_time) - to_unix_timestamp(lag_time))/60 > 10, 1,0) flag  -- 将日期转为时间戳,秒为单位
from
(
   select
     uid,
     start_time,
     end_time,
     flow,
     lag(end_time,1,start_time) over(partition by uid order by start_time) lag_time
   from
     tb_flowCount
)

--
+---+-------------------+-------------------+----+----+
|uid|         start_time|           end_time|flow|flag|
+---+-------------------+-------------------+----+----+
|  1|2020-02-18 14:20:30|2020-02-18 14:46:30|  20|   0|
|  1|2020-02-18 14:47:20|2020-02-18 15:20:30|  30|   0|
|  1|2020-02-18 15:37:23|2020-02-18 16:05:26|  40|   1|
|  1|2020-02-18 16:06:27|2020-02-18 17:20:49|  50|   0|
|  1|2020-02-18 17:21:50|2020-02-18 18:03:27|  60|   0|
|  3|2020-02-18 14:39:58|2020-02-18 15:35:53|  20|   0|
|  3|2020-02-18 15:36:39|2020-02-18 15:24:54|  30|   0|
|  2|2020-02-18 14:18:24|2020-02-18 15:01:40|  20|   0|
|  2|2020-02-18 15:20:49|2020-02-18 15:30:24|  30|   1|
|  2|2020-02-18 16:01:23|2020-02-18 16:40:32|  40|   1|
|  2|2020-02-18 16:44:56|2020-02-18 17:40:52|  50|   0|
+---+-------------------+-------------------+----+----+

3

select
  uid,
  start_time,
  end_time,
  flow,
  sum(flag) over(partition by uid order by start_time) sum_flag
from
(
  select
    uid,
    start_time,
    end_time,
    flow,
    if((to_unix_timestamp(start_time) - to_unix_timestamp(lag_time))/60 > 10, 1,0) flag  -- 将日期转为时间戳,秒为单位
  from
   (
     select
       uid,
       start_time,
       end_time,
       flow,
       lag(end_time,1,start_time) over(partition by uid order by start_time) lag_time
     from
       tb_flowCount
   )
)

--+---+-------------------+-------------------+----+--------+
|uid|         start_time|           end_time|flow|sum_flag|
+---+-------------------+-------------------+----+--------+
|  1|2020-02-18 14:20:30|2020-02-18 14:46:30|  20|       0|
|  1|2020-02-18 14:47:20|2020-02-18 15:20:30|  30|       0|
|  1|2020-02-18 15:37:23|2020-02-18 16:05:26|  40|       1|
|  1|2020-02-18 16:06:27|2020-02-18 17:20:49|  50|       1|
|  1|2020-02-18 17:21:50|2020-02-18 18:03:27|  60|       1|
|  3|2020-02-18 14:39:58|2020-02-18 15:35:53|  20|       0|
|  3|2020-02-18 15:36:39|2020-02-18 15:24:54|  30|       0|
|  2|2020-02-18 14:18:24|2020-02-18 15:01:40|  20|       0|
|  2|2020-02-18 15:20:49|2020-02-18 15:30:24|  30|       1|
|  2|2020-02-18 16:01:23|2020-02-18 16:40:32|  40|       2|
|  2|2020-02-18 16:44:56|2020-02-18 17:40:52|  50|       2|
+---+-------------------+-------------------+----+--------+

4

select
  uid,
  min(start_time) start_time,
  max(end_time) end_time,
  sum(flow) flow
from
(
  select
    uid,
    start_time,
    end_time,
    flow,
    sum(flag) over(partition by uid order by start_time) sum_flag
  from
  (
    select
      uid,
      start_time,
      end_time,
      flow,
      if((to_unix_timestamp(start_time) - to_unix_timestamp(lag_time))/60 > 10, 1,0) flag  -- 将日期转为时间戳,秒为单位
    from
     (
       select
         uid,
         start_time,
         end_time,
         flow,
         lag(end_time,1,start_time) over(partition by uid order by start_time) lag_time
       from
         tb_flowCount
     )
  )
)
group by uid,sum_flag
--
+---+-------------------+-------------------+---------+
|uid|         start_time|           end_time|     flow|
+---+-------------------+-------------------+---------+
|  1|2020-02-18 14:20:30|2020-02-18 15:20:30|       50|
|  1|2020-02-18 15:37:23|2020-02-18 18:03:27|      150|
|  3|2020-02-18 14:39:58|2020-02-18 15:35:53|       50|
|  2|2020-02-18 14:18:24|2020-02-18 15:01:40|       20|
|  2|2020-02-18 15:20:49|2020-02-18 15:30:24|       30|
|  2|2020-02-18 16:01:23|2020-02-18 17:40:52|       90|
+---+-------------------+-------------------+---------+
  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: SparkSQLSpark生态系统中的一个组件,它提供了一种基于结构化数据的编程接口,可以让用户使用SQL语言来查询和处理数据。SparkSQL支持多种数据源,包括Hive、JSON、Parquet等,同时也支持将查询结果输出到不同的存储系统中。SparkSQL还提供了DataFrame和Dataset两个API,可以让用户以类似于关系型数据库的方式来处理数据。通过SparkSQL用户可以更方便地进行数据分析和处理,提高数据处理效率和准确性。 ### 回答2: SparkSQLSpark生态系统中的一部分,能够提供高效的数据处理和快速的查询操作。它支持执行结构化数据处理的SQL语法和DataFrame API,并可与Python、Java、Scala进行交互。 在学习SparkSQL之前,需要掌握Spark基础的RDD编程,理解Spark RDD的概念和操作。接下来,了解SparkSQL的核心组件,即Catalyst Optimizer和Tungsten Execution Engine。 Catalyst Optimizer是SparkSQL的查询优化器,它能够对查询语句进行优化,提高查询速度。它可以通过逻辑优化、物理执行优化和代码生成优化来提高查询效率。 Tungsten Execution Engine是SparkSQL的执行引擎,它通过使用自定义的内存管理和计算支持来提高性能。Tungsten的内存管理器可以在JVM之外使用本地内存,这在处理大型数据集时非常有用。 了解了这些基础概念后,就可以开始学习SparkSQL的语法和操作了。SparkSQL支持的语法类似于传统的SQL语法,但也增加了类似于函数式编程的特性。 在SparkSQL中,数据可以表示为DataFrame或DataSet对象。DataFrame是一个分布式的数据表,类似于传统数据库中的表。DataSet是一个强类型的数据集,可以使用Java或Scala编写类型安全的数据处理逻辑。 SparkSQL还支持连接多个数据源,包括Hive、MySQL、PostgreSQL等。可以使用Spark SQL中的数据源API或JDBC API创建一个JDBC连接并访问数据。 除了基本的查询操作,SparkSQL还提供了许多高级操作,如窗口函数、聚合函数、分组集函数等,这些操作可以帮助用户更高效地处理数据。 最后,还要注意SparkSQL的优化和调试。可以通过查看Spark Web UI、使用count()、explain()函数等方法来进行调试和优化。 总之,SparkSQLSpark生态系统中的一个重要组成部分,它提供了高效的数据处理和快速的查询操作,是处理和分析大型数据集时的重要工具。 ### 回答3: Spark SQLSpark生态系统中的一个SQL执行引擎,使用它可以方便的在Spark程序中操作结构化的数据。本文将介绍Spark SQL的使用方法,包括如何使用Spark SQL查询结构化数据、如何使用DataFrame和DataSet API来处理数据,以及如何将DataFrame和DataSet与RDD进行交互。 使用Spark SQL查询结构化数据 Spark SQL通过在Spark程序中使用SQL语句来查询结构化数据。在查询之前,需要加载数据文件并将其转换为DataFrame或DataSet。加载数据文件的方法包括加载文本文件、JSON文件、CSV文件等。加载数据文件后,可以使用SQL语句通过DataFrame或DataSet进行数据查询,并将查询结果打印输出或写入文件。以下是实现这些操作的代码示例: //加载文本文件 val lines = spark.read.textFile("file.txt") //加载JSON文件 val json = spark.read.json("file.json") //加载CSV文件 val csv = spark.read.format("csv").option("header", "true").load("file.csv") //使用SQL语句查询数据 json.createOrReplaceTempView("people") val sqlDF = spark.sql("SELECT * FROM people") //将查询结果打印输出 sqlDF.show() //将查询结果写入文件 sqlDF.write.format("csv").save("result.csv") 使用DataFrame和DataSet API处理数据 Spark SQL提供了DataFrame和DataSet API来处理数据。DataFrame是一种带有命名列的分布式数据集合,DataSet是DataFrame的类型安全版本。使用这些API可以操作DataFrame和DataSet中的列和行数据,并进行转换、聚合和合并等操作。以下是使用DataFrame API操作结构化数据的示例代码: //创建DataFrame val df = spark.read.json("file.json") //显示DataFrame的Schema df.printSchema() //选择特定列进行查询 df.select("name", "age").show() //按name和age进行聚合统计 df.groupBy("name", "age").count().show() //将DataFrame转换为DataSet case class Person(name: String, age: Long) val ds = df.as[Person] //使用DataSet API查询 ds.filter(p => p.age > 18).show() 将DataFrame和DataSet与RDD进行交互 Spark SQL支持DataFrame、DataSet和RDD之间的相互转换。通过这种方式,可以在RDD和DataFrame或DataSet之间进行无缝转换,并执行相应的操作。以下是一些将DataFrame和DataSet与RDD进行交互的示例代码: //将RDD转换为DataFrame val rdd = sc.parallelize(Seq((1, "John"), (2, "Mike"), (3, "Lucy"))) val df = rdd.toDF("id", "name") //将DataFrame转换为RDD val rdd = df.rdd //将DataSet转换为RDD val ds = Seq(Person("John", 23), Person("Mike", 32), Person("Lucy", 18)).toDS() val rdd = ds.rdd 总之,Spark SQLSpark生态系统中的一个非常有用的工具,通过使用它可以方便地进行数据查询和处理。在使用Spark SQL时,需要理解如何加载和查询数据文件、如何使用DataFrame和DataSet API来处理数据,以及如何将DataFrame和DataSet与RDD进行交互。当然,在实际使用中,还需要根据具体情况进行进一步学习和实践。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值