大数据学习之SparkSQL(补充)

SparkSQL

1、SparkSql初识案例 :WordCount
  • spark sql处理数据的步骤
  • 1、读取数据源
  • 2、将读取到的DF注册成一个临时视图
  • 3、使用sparkSession的sql函数,编写sql语句操作临时视图,返回的依旧是一个DataFrame
  • 4、将结果写出到hdfs上
import org.apache.spark.SparkContext
import org.apache.spark.sql.{
   DataFrame, Dataset, Row, SaveMode, SparkSession}


object Demo1WordCount {
   
  def main(args: Array[String]): Unit = {
   
    //创建编写spark sql的环境
    val sparkSession: SparkSession = SparkSession
    /**
     * 用于创建或配置 SparkSession 实例的一个构建器(Builder)模式的应用
     * 使用 SparkSession.builder(),你可以链式地设置各种配置选项,
     * 并最终通过调用 .getOrCreate() 方法来获取一个 SparkSession 实例。
     */
      .builder()
      // 执行模式:本地执行
      .master("local")
      // 名称
      .appName("sql语法风格编写WordCount")
      // 获取SparkSession.builder()创建的 SparkSession 实例
      .getOrCreate()

    /**
     * spark sql是spark core的上层api,如果要想使用rdd的编程
     * 可以直接通过sparkSession获取SparkContext对象
     */
        val context: SparkContext = sparkSession.sparkContext

    //spark sql的核心数据类型是DataFrame(注意与RDD的区别)
    val df1: DataFrame = sparkSession.read
      .format("csv") // 读取csv格式的文件,但是实际上这种做法可以读取任意分隔符的文本文件
      .option("sep", "\n") //指定读取数据的列与列之间的分隔符
      .schema("line STRING") // 指定表的列字段 包括列名和列数据类型
      // 读取文件数据
      .load("spark/data/wcs/words.txt")

    //    println(df1)
    //查看DataFrame的数据内容
    //    df1.show()
    //查看表结构
    //    df1.printSchema()

    /**
     * sql语句是无法直接作用在DataFrame上面的
     * 需要提前将要使用sql分析的DataFrame注册成一张表(临时视图)
     */
    //老版本的做法将df注册成一张表
    //    df1.registerTempTable("wcs")
    df1.createOrReplaceTempView("wcs")

    /**
     * 编写sql语句作用在表上
     * sql语法是完全兼容hive语法
     */
    val df2: DataFrame = sparkSession.sql(
      """
        |select
        |t1.word,
        |count(1) as counts
        |from(
        |select
        |explode(split(line,'\\|')) as word
        |from wcs) t1 group by t1.word
        |""".stripMargin)
    //    df2.show()

    //通过观察源码发现,DataFrame底层数据类型其实就是封装了DataSet的数据类型
    // 对DataFrame或Dataset进行重分区,Spark将这个DataFrame或Dataset的数据重新分配到1个分区中。
    val resDS: Dataset[Row] = df2.repartition(1)

    /**
     * 将计算后的DataFrame保存到本地磁盘文件中
     */
    resDS.write
      .format("csv") //默认的分隔符是英文逗号
      //      .option("sep","\t")
      .mode(SaveMode.Overwrite) // 如果想每次覆盖之前的执行结果的话,可以在写文件的同时指定写入模式,使用模式枚举类
      .save("spark/data/sqlout1") // 保存的路径其实是指定的一个文件夹

  }
}

DataFrame DSL

Spark SQL中的DataFrame DSL(Domain Specific Language,领域特定语言)是一种用于处理DataFrame的编程风格,它允许开发者以命令式的方式,通过调用API接口来操作DataFrame。这种风格**介于代码和纯SQL之间,**提供了一种更加灵活和强大的数据处理方式。

DataFrame DSL(Domain Specific Language,领域特定语言)中的API接口是一系列用于操作DataFrame的函数和方法。

1、DSL处理WordCount
import org.apache.spark.sql.{
   DataFrame, SaveMode, SparkSession}

object Demo2DSLWordCount {
   
  def main(args: Array[String]): Unit = {
   
    //创建SparkSession对象
    val sparkSession: SparkSession = SparkSession.builder()
      .master("local")
      .appName("DSL语法风格编写spark sql")
      .getOrCreate()

    val df1: DataFrame = sparkSession.read
      .format("csv")
      .schema("line STRING")
      .option("sep", "\n")
      .load("spark/data/wcs/words.txt")

    /**
     * 如果要想使用DSL语法编写spark sql的话,需要导入两个隐式转换
     */
    //将sql中的函数,封装成spark程序中的一个个的函数直接调用,以传参的方式调用
    import org.apache.spark.sql.functions._
    //主要作用是,将来可以在调用的函数中,使用$函数,将列名字符串类型转成一个ColumnName类型
    //而ColumnName是继承自Column类的
    import sparkSession.implicits._

    //老版本聚合操作
    //    df1.select(explode(split($"line","\\|")) as "word")
    //      .groupBy($"word")
    //      .count().show()

    //新版本聚合操作
    // .as("word") == as "word" 
    val resDF: DataFrame = df1.select(explode(split($"line", "\\|")) as "word")
      .groupBy($"word")
      .agg(count($"word") as "counts")

    resDF
      // 重分区
      .repartition(1)
      .write
      .format("csv")
      .option("sep","\t")
      .mode(SaveMode.Overwrite)
      .save("spark/data/sqlout2")

  }
}
2、DSLApi
import org.apache.spark.sql.expressions.Window
import org.apache.spark.sql.{
   DataFrame, SaveMode, SparkSession, expressions}


object Demo3DSLApi {
   
  def main(args: Array[String]): Unit = {
   
    //创建SparkSession对象
    val sparkSession: SparkSession = SparkSession.builder()
      .config("spark.sql.shuffle.partitions","1")
      .master("local")
      .appName("DSL语法风格编写spark sql")
      .getOrCreate()

    /**
     * 如果要想使用DSL语法编写spark sql的话,需要导入两个隐式转换
     */
    //将sql中的函数,封装成spark程序中的一个个的函数直接调用,以传参的方式调用
    import org.apache.spark.sql.functions._
    //主要作用是,将来可以在调用的函数中,使用$函数,将列名字符串类型转成一个ColumnName类型
    //而ColumnName是继承自Column类的
    import sparkSession.implicits._

    /**
     * 读取json数据文件,转成DF
     * 读取json数据的时候,是不需要指定表结构,可以自动根据json的键值来构建DataFrame
     */
    //老版本的读取json数据的方式
//        val df1: DataFrame = sparkSession.read
//          .format("json")
//          .load("spark/data/students.json")

    val df1: DataFrame = sparkSession.read
      // 由于是json数据,数据中就有它们的列名,所以无需再为它们设置列名
      .json("spark/data/students.json")

    //默认显示20行数据
    //    df1.show()
    //传入要查看的行数
    //    df1.show(100)
    //传入第二个参数 truncate = false,观察的更加详细,默认每一列只会保留20个字符
//        df1.show(10,truncate = false)

    /**
     * DSL语法的第一个函数 select
     * 类似于纯sql语法中的select关键字,传入要查询的列
     */
//    select name,clazz from xxx;
            df1.select("name","age").show()
        df1.select($"name", $"age").show()
    //查询每个学生的姓名,原本的年龄,年龄+1
        df1.select("name", "age").show()
    /**
     * 与select功能差不多的查询函数
     * 如果要以传字符串的形式给到select的话,并且还想对列进行表达式处理的话,可以使用selectExpr函数
     */
        df1.selectExpr("name", "age", "age+1 as new_age").show()
    //如果想要使用select函数查询的时候对列做操作的话,可以使用$函数将列变成一个对象
        df1.select($"name", $"age", $"age" + 1 as "new_age").show()

    /**
     * DSL语法函数:where
     * === : 类似于sql中的= 等于某个值
     * =!= : 类似于sql中的!=或者<>  不等于某个值
     */
        df1.where("gender='男'").show()
        df1.where("gender='男' and substring(clazz,0,2)='理科'").show()
    //TODO 建议使用隐式转换中的功能进行处理过滤,$"gender",将gender转换成一个ColumnName类对象
    //过滤出男生且理科的
        df1.where($"gender" === "男" and substring($"clazz",0,2) === "理科").show()
    //过滤出女生且理科的
        df1.where($"gender" =!= "男" and substring($"clazz",0,
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值