开始更新啦
Spark SQL
之前说过,SQl写得好,工作随便找。今天就从最开始的Spark SQL进行讲解,之后还会讲解一个项目,关于TMDB的一个Spark实验
创建DataFrame
创建dataFrame的方法很多,之前的博客里面通过读取json文件进行创建DataFrame,今天用列表创建DataFrame。
//配置Spark 环境
val spark = SparkSession.builder .master("local[1]") .appName("SparkByExamples.com") .getOrCreate()
//创建数据
val data = Seq(("James","Smith","USA","CA"),
("Michael","Rose","USA","NY"),
("Robert","Williams","USA","CA"),
("Maria","Jones","USA","FL") )
//创建schema,就是所谓的表头,字段名
val columns = Seq("firstname","lastname","country","state")
import spark.implicits._
val df = data.toDF(columns:_*)
df.show(false)
可以看到之前创建的columns作为了schema。为了验证这个猜想,下面打印一下schema
df.printSchema()
选择单列和多列
和我们用SQL一样,DSL中也是使用select进行查询。
查询的api多个重载方法,下面来看一看
df.select("firstname","lastname").show()
df.select($"firstname",$"lastname").show()
df.select(df("firstname"),df("lastname")).show()
//上面的三种方式是经常用到的,如果想要实现 name,age,age+1
那么就需要使用$符号
df.select("name","age",$"age" + 1).show()
下面这一种是调用相关的包进行select。
import org.apache.spark.sql.functions.col df.select(col("firstname").alias("fname"),col("lastname")).show()
//上面这个查询将字段名字进行改名,来看一下改名后的结果把
选择所有列
第一种方法,直接*,最为方便
df.select("*").show()
第二种方法
使用df.columns获取dataframe上的所有列,也就是Array[String],之后使用Map转换类型Array[Column].也就是将字段名包装到数组中。
val columnsAll = df.columns.map(m => col(m))
df.select(columnsAll:_*).show()
选择前N列
- take
//take返回的是数组,因此想要看到数据需要遍历打印出来 df.select("*").take(20).foreach(println(_))
2.map方法
df.select(df.columns.slice(0,2).map(m => col(m)):_*).show()
//这里的slice不是限制的打印行数,限制的是打印列数 //(0,2) 打印的是前两列
按照位置或者索引打印列
从索引中打印列
df.select(df.columns(3)).show()
按照索引位置,从0开始,0,1,2,3.这里只打印第四个列
2.按照位置打印列
df.select(df.columns.slice(2,4).map(m => col(m)):_*).show()
从下标为2开始,4之前结尾
选择嵌套结构列
这是一个比较重要的内容,首先看一下嵌套的内容
如果将上面的内容当作dataframe。就会有三个大字段。在第一个大字段里面,嵌套了三个字段。
那么如何对上面的数据进行增加字段名呢?
StructType结构类型,是所有StructField对象的集合。StructField就是字段的名称,类型。之后会在博客里面讲解StructField和StructType两个结构化类型。
import org.apache.spark.sql.types.{StringType, StructType}
//使用Row对象进行嵌套
val data2 = Seq(Row(Row("James","","Smith"),"OH","M"),
Row(Row("Anna","Rose",""),"NY","F"),
Row(Row("Julia","","Williams"),"OH","F"),
Row(Row("Maria","Anne","Jones"),"NY","M"),
Row(Row("Jen","Mary","Brown"),"NY","M"),
Row(Row("Mike","Mary","Williams"),"OH","M") )
//创建StructType,使用add方法增加每个字段的名字以及类型
//即 StringType 字符串类型
val schema = new StructType().add("name",new StructType().add("firstname",StringType) .add("middlename",StringType) .add("lastname",StringType)).add("state",StringType) .add("gender",StringType)
//创建dataframe,第一个参数是RDD[Row],第二个参数是StructType
val df2 = sparkSession.createDataFrame( sparkSession.sparkContext.parallelize(data2),schema)
df2.printSchema() df2.show(false)
下面看一下,打印后的Schema把
看一下数据
单独的展示name字段
df2.select($"name").show()
如果想要看嵌套字段name里面的特定列,可以明确的指定
df2.select("name.firstname").show()
关于上面的内容,着重需要注意的就是后面的嵌套结构,因为在后面的TDMB项目中,会有嵌套的字段,就会需要到StructField和StructType。
碎碎念
下午应该会该更新相关的内容,也就是StructField和StructType结构类型的相关知识。这篇博客中,应该重点看一下后面的嵌套字段。