Spark SQL是一个用来处理结构化数据的Spark组件,是Spark上一个分布式的SQL查询引擎,并拥有自己的SQL解析器。
Spark SQL 特点:
Spark SQL的执行流程:
Spark SQL提供了一个叫做DataFrames的可编程抽象数据模型。DataFrame是以“命名列”方式(类似关系表的字段定义)组织起来的分布式数据集,与传统关系型数据库中的表结构类似。不同于RDD,DataFrames封装了数据的结构信息。
Spark SQL交互入口:
import.sqlContext.implicits._
val conf= new SparkConf().setAppName("SQL_Advanced_case").setMaster("local")
val sc=new SparkContext(conf)
val sqlContext=new SQLContext(sc)
val spark= SparkSession.builder().appName(“SparkSQLTest”).getOrCreate()
创建DataFrame:
val students = sqlContext.parquetFile(“hdfs://node01:9000/sqldata/ students.parquet")
保存DataFrame:
Spark SQL简单案例:
链接: https://pan.baidu.com/s/1mhO5vkO 密码: 5f9w
————————————案例1————————————
spark-shell下操作:
import org.apache.spark.sql.types._
import org.apache.spark.sql._
import org.apache.spark._
import sqlContext.implicits._
1.利用反射机制创建students.txt对应的DataFrame,其中包含id、name、age三个字段。
case class Student(id: String, name : String, age: Int)
val students_rdd=sc.textFile("hdfs://node01:9000/sqldata/students.txt").map(_.split(",")).map(p => Student(p(0), p(1), p(2).trim.toInt))
val students=students_rdd.toDF()
其中,p(2).trim.toInt
将学生表中的age字段数据整理转化为Int
2.查看所有学生的姓名
students.select(col("name")).show
students.select($"age").show
3.查询所有学生的年龄,并按照年龄降序排序。
students.select($"age").orderBy(col("age").desc).show
students.select($"age").orderBy($"age".desc).show
4.查询年龄小于19或年龄大于21的所有学生。
students.registerTempTable("tb_students")
sqlContext.sql("select name,age from tb_students where (age>21) or (age<19)").show
5.计算所有学生的平均年龄。
sqlContext.sql("select avg(age) as averageAge from tb_students").show
sqlContext.sql("select sum(age)/10 as averageAge from tb_students").show
6.将age字段重命名为stu_age。
students.withColumnRenamed("age","stu_age").show
7.添加scholarship字段,每个学生的scholarship项是其龄*20。
students.withColumn("scholarship",col("age")*20).show
students.withColumn("scholarship",$"age"*20).show
8.将添加scholarship字段后的DataFrame分别以Parquet和JSON格式保存至HDFS上。
val students_j=students.withColumn("scholarship",col("age")*20).write.save("hdfs://node01:9000/sqldata/students_j.json")
val students_p=students.withColumn("scholarship",col("age")*20).write.save("hdfs://node01:9000/sqldata/students_p.parquet")
9.利用自定义接口创建scores.txt对应的DataFrame,其中包含id、course_id、score三个字段。
val scores_rdd=sc.textFile("hdfs://node01:9000/sqldata/scores.txt")
val schemaString="id course_id score"
val schema=StructType(schemaString.split(" ").map(fieldname=> StructField(fieldname, StringType, true)))
val rowRDD=scores_rdd.map(_.split(",")).map(p=>Row(p(0), p(1), p(2).trim))
val scores=sqlContext.createDataFrame(rowRDD, schema)
scores.registerTempTable("tb_scores")
10.按照课程编号分组,查看每门课的平均成绩,并按课程编号升序排序。
sqlContext.sql("select avg(score) as averageScore from tb_scores group by course_id").show
11.按照课程编号分组,查看个学生的姓名和其所有课程的平均成绩,并在统计结果中筛选出平均成绩大于72的同学。
sqlContext.sql("select id,avg(score) as averageScore from tb_scores group by id having averageScore>72 order by averageScore desc").show
————————————案例2————————————
首先构建数据库Students,然后分别创建上述表,在此基础上实现以下查询:
1.查询创建的五个表的概要信息。
2.查询各院系学生总数。
3.查询各院系学生奖学金的总和并排序。
4.查询各院系学生的平均学分并排序。
5.统计各学院每年学生参与创新项目所获得的创新学分数总数。
sqlContext.sql("CREATE DATABASE STUDENTS")
sqlContext.sql("USE STUDENTS")
创建学生信息表students
sqlContext.sql("CREATE TABLE IF NOT EXISTS students(id STRING, name STRING, gender STRING, age INT, year STRING, dep_id STRING) ROW FORMAT DELIMITED FIELDS TERMINATED BY ',' LINES TERMINATED BY '\n'")
加载数据
sqlContext.sql("LOAD DATA INPATH 'hdfs://node01:9000/sqldata/students2.txt' OVERWRITE INTO TABLE students")
查询概要
sqlContext.sql("select * from students").printSchema
同理,创建、加载、查询其余四个表
查询各院系学生总数
sqlContext.sql("select b.name, count(a.id) from students a join departments b on a.dep_id=b.dep_id group by b.name").show
查询各院系学生奖学金的总和并排序
sqlContext.sql("select b.name,sum(c.amount) as sum from students a join departments b on a.dep_id=b.dep_id join scholarship c on a.id = c.id group by b.name order by sum asc").show
sqlContext.sql("select b.name,sum(c.amount) as sum from students a join departments b on a.dep_id=b.dep_id join scholarship c on a.id = c.id group by b.name order by sum desc").show
查询各院系学生的平均学分并排序
sqlContext.sql("select b.name,avg(c.credit) as average_credit from students a join departments b on a.dep_id=b.dep_id join scores c on a.id = c.id group by b.name order by average_credit").show
统计各学院每年学生参与创新项目所获得的创新学分数总数
sqlContext.sql("select b.name, h.year,sum(h.pro_score) as sum from(select a.id,p.year,p.level*( p.theory+p.practice)/16 as pro_score,a.dep_id from projects p join students a on a.id=p.id) h join departments b on h.dep_id=b.dep_id group by b.name, h.year").show