表和数据

/*
 Navicat Premium Data Transfer

 Source Server         : pdm
 Source Server Type    : MySQL
 Source Server Version : 50173
 Source Host           : 192.168.1.100:3306
 Source Schema         : test

 Target Server Type    : MySQL
 Target Server Version : 50173
 File Encoding         : 65001

 Date: 12/06/2019 11:05:31
*/

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for Course
-- ----------------------------
DROP TABLE IF EXISTS `Course`;
CREATE TABLE `Course`  (
  `CId` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `Cname` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `TId` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of Course
-- ----------------------------
INSERT INTO `Course` VALUES ('01', '语文', '02');
INSERT INTO `Course` VALUES ('02', '数学', '01');
INSERT INTO `Course` VALUES ('03', '英语', '03');

-- ----------------------------
-- Table structure for SC
-- ----------------------------
DROP TABLE IF EXISTS `SC`;
CREATE TABLE `SC`  (
  `SId` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `CId` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `score` decimal(18, 1) DEFAULT NULL
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of SC
-- ----------------------------
INSERT INTO `SC` VALUES ('01', '01', 80.0);
INSERT INTO `SC` VALUES ('01', '02', 90.0);
INSERT INTO `SC` VALUES ('01', '03', 99.0);
INSERT INTO `SC` VALUES ('02', '01', 70.0);
INSERT INTO `SC` VALUES ('02', '02', 60.0);
INSERT INTO `SC` VALUES ('02', '03', 80.0);
INSERT INTO `SC` VALUES ('03', '01', 80.0);
INSERT INTO `SC` VALUES ('03', '02', 80.0);
INSERT INTO `SC` VALUES ('03', '03', 80.0);
INSERT INTO `SC` VALUES ('04', '01', 50.0);
INSERT INTO `SC` VALUES ('04', '02', 30.0);
INSERT INTO `SC` VALUES ('04', '03', 20.0);
INSERT INTO `SC` VALUES ('05', '01', 76.0);
INSERT INTO `SC` VALUES ('05', '02', 87.0);
INSERT INTO `SC` VALUES ('06', '01', 31.0);
INSERT INTO `SC` VALUES ('06', '03', 34.0);
INSERT INTO `SC` VALUES ('07', '02', 89.0);
INSERT INTO `SC` VALUES ('07', '03', 98.0);

-- ----------------------------
-- Table structure for Student
-- ----------------------------
DROP TABLE IF EXISTS `Student`;
CREATE TABLE `Student`  (
  `SId` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `Sname` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `Sage` datetime DEFAULT NULL,
  `Ssex` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of Student
-- ----------------------------
INSERT INTO `Student` VALUES ('01', '赵雷', '1990-01-01 00:00:00', '男');
INSERT INTO `Student` VALUES ('02', '钱电', '1990-12-21 00:00:00', '男');
INSERT INTO `Student` VALUES ('03', '孙风', '1990-12-20 00:00:00', '男');
INSERT INTO `Student` VALUES ('04', '李云', '1990-12-06 00:00:00', '男');
INSERT INTO `Student` VALUES ('05', '周梅', '1991-12-01 00:00:00', '女');
INSERT INTO `Student` VALUES ('06', '吴兰', '1992-01-01 00:00:00', '女');
INSERT INTO `Student` VALUES ('07', '郑竹', '1989-01-01 00:00:00', '女');
INSERT INTO `Student` VALUES ('09', '张三', '2017-12-20 00:00:00', '女');
INSERT INTO `Student` VALUES ('10', '李四', '2017-12-25 00:00:00', '女');
INSERT INTO `Student` VALUES ('11', '李四', '2012-06-06 00:00:00', '女');
INSERT INTO `Student` VALUES ('12', '赵六', '2013-06-13 00:00:00', '女');
INSERT INTO `Student` VALUES ('13', '孙七', '2014-06-01 00:00:00', '女');

-- ----------------------------
-- Table structure for Teacher
-- ----------------------------
DROP TABLE IF EXISTS `Teacher`;
CREATE TABLE `Teacher`  (
  `TId` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL,
  `Tname` varchar(10) CHARACTER SET utf8 COLLATE utf8_general_ci DEFAULT NULL
) ENGINE = MyISAM CHARACTER SET = utf8 COLLATE = utf8_general_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of Teacher
-- ----------------------------
INSERT INTO `Teacher` VALUES ('01', '张三');
INSERT INTO `Teacher` VALUES ('02', '李四');
INSERT INTO `Teacher` VALUES ('03', '王五');

SET FOREIGN_KEY_CHECKS = 1;

准备环境

val sc = new SparkSession
    .Builder()
      .appName("source_data_mysql001")
      .master("local")
      .getOrCreate()
    val url = "jdbc:mysql://192.168.1.100:3306/Strengthen"

    val SC = "SC"
    val df_SC = sc.read.jdbc(url, SC, dbConnProperties())

    df_SC.show() //使用一个action算子来检查是否能读取数据

1.1查询" 01 “课程比” 02 "课程成绩高的学生id及课程分数

val frame1 = sc.sql("select * from sc s1 inner join SC s2 " +
      "on s1.SId = s2.SId " +
      "where s1.CId = '01' and s2.CId = '02' and s1.score > s2.score")
    frame1.show()

1.1 查询同时存在" 01 “课程和” 02 "课程的情况

spark2是支持子查询的

val frame = sc.sql("select * from sc s1 " +
      "where s1.SId in  " +
      "(select distinct(s2.SId) from sc s2 where s2.CId = '02') " +
      "and s1.CId = '01'")

    frame.show()
+---+---+-----+
|SId|CId|score|
+---+---+-----+
| 01| 01| 80.0|
| 05| 01| 76.0|
| 03| 01| 80.0|
| 02| 01| 70.0|
| 04| 01| 50.0|
+---+---+-----+

2.0语法和mysql感觉没啥区别,where和inner join on也是效果一样

val frame = sc.sql(
      "select * from sc s1,sc s2 " +
        "where s1.SId = s2.SId " +
        "and s1.CId = '01' " +
        "and s2.CId = '02' " +
        "order by s1.SId")
+---+---+-----+---+---+-----+
|SId|CId|score|SId|CId|score|
+---+---+-----+---+---+-----+
| 01| 01| 80.0| 01| 02| 90.0|
| 02| 01| 70.0| 02| 02| 60.0|
| 03| 01| 80.0| 03| 02| 80.0|
| 04| 01| 50.0| 04| 02| 30.0|
| 05| 01| 76.0| 05| 02| 87.0|
+---+---+-----+---+---+-----+

1.2 查询存在" 01 “课程但可能不存在” 02 "课程的情况(不存在时显示为 null )
重点在于之前的关于join on and 和where and的区别
on and 把02不存在的设置为null
where过滤只保留01课程

val frame = sc.sql("select * from sc s1 " +
      "left join sc s2 " +
      "on s1.SId = s2.SId " +
      "and s2.CId = '02' " +
      "where s1.CId = '01' order by s1.SId")
+---+---+-----+----+----+-----+
|SId|CId|score| SId| CId|score|
+---+---+-----+----+----+-----+
| 01| 01| 80.0|  01|  02| 90.0|
| 02| 01| 70.0|  02|  02| 60.0|
| 03| 01| 80.0|  03|  02| 80.0|
| 04| 01| 50.0|  04|  02| 30.0|
| 05| 01| 76.0|  05|  02| 87.0|
| 06| 01| 31.0|null|null| null|
+---+---+-----+----+----+-----+

1.3 查询不存在" 01 “课程但存在” 02 "课程的情况
join on and 和where and,然后过滤得到 is null
但是例如01,03都不存在,02存在,感觉有问题

val frame = sc.sql("select * from sc s1 " +
      "left join sc s2 " +
      "on s1.SId = s2.SId " +
      "and s2.CId = '01' "+
      "where s1.CId = '02'  and s2.CId is null " +
      "order by s1.SId")
+---+---+-----+----+----+-----+
|SId|CId|score| SId| CId|score|
+---+---+-----+----+----+-----+
| 07| 02| 89.0|null|null| null|
+---+---+-----+----+----+-----+
val frame = sc.sql("select * from sc s1 " +
      "where s1.SId not in " +
      "(select SId from sc where sc.CId = '01') " +
      "and s1.CId = '02' " +
      "order by s1.SId")
|SId|CId|score|
+---+---+-----+
| 07| 02| 89.0|
+---+---+-----+

2 查询平均成绩大于等于 60 分的同学的学生编号和学生姓名和平均成绩
先查询在join,因为spark不可以在使用group by时查询没有出现在grou by 后面的字段

select stu.*,scavg.avg from stu join 
(selectSId,avg(sc.score) as avg from sc 
group by SId having avg(sc.score) >= 60) scavg  
on stu.SId = scavg.SId
+---+-----+-------------------+----+--------+
|SId|Sname|               Sage|Ssex|     avg|
+---+-----+-------------------+----+--------+
| 07| 郑竹|1989-01-01 00:00:00|  女|93.50000|
| 01| 赵雷|1990-01-01 00:00:00|  男|89.66667|
| 05| 周梅|1991-12-01 00:00:00|  女|81.50000|
| 03| 孙风|1990-12-20 00:00:00|  男|80.00000|
| 02| 钱电|1990-12-21 00:00:00|  男|70.00000|
+---+-----+-------------------+----+--------+

3 查询在 SC 表存在成绩的学生信息
子查询性能消耗太大,不建议,所以这样写

select stu.* from stu 
inner join (select distinct(SID) as id 
from sc where score is not null) sc 
on stu.SId = sc.id

+---+-----+-------------------+----+
|SId|Sname|               Sage|Ssex|
+---+-----+-------------------+----+
| 07| 郑竹|1989-01-01 00:00:00|  女|
| 01| 赵雷|1990-01-01 00:00:00|  男|
| 05| 周梅|1991-12-01 00:00:00|  女|
| 03| 孙风|1990-12-20 00:00:00|  男|
| 02| 钱电|1990-12-21 00:00:00|  男|
| 06| 吴兰|1992-01-01 00:00:00|  女|
| 04| 李云|1990-12-06 00:00:00|  男|
+---+-----+-------------------+----+

这样也行,建议第一种

select distinct(stu.*) from sc join stu 
on sc.SId = stu.SId 
where score is not null

4.1 查询所有同学的学生编号、学生姓名、选课总数、所有课程的总成绩(没成绩的显示为 null )

select stu.*,s.count,s.sum from stu 
left join 
(select SId,count(DISTINCT CId) as count,sum(score) as sum 
from sc group by SId) as s 
on stu.SId = s.SId 
order by stu.SId
+---+-----+-------------------+----+-----+-----+
|SId|Sname|               Sage|Ssex|count|  sum|
+---+-----+-------------------+----+-----+-----+
| 01| 赵雷|1990-01-01 00:00:00|  男|    3|269.0|
| 02| 钱电|1990-12-21 00:00:00|  男|    3|210.0|
| 03| 孙风|1990-12-20 00:00:00|  男|    3|240.0|
| 04| 李云|1990-12-06 00:00:00|  男|    3|100.0|
| 05| 周梅|1991-12-01 00:00:00|  女|    2|163.0|
| 06| 吴兰|1992-01-01 00:00:00|  女|    2| 65.0|
| 07| 郑竹|1989-01-01 00:00:00|  女|    2|187.0|
| 09| 张三|2017-12-20 00:00:00|  女| null| null|
| 10| 李四|2017-12-25 00:00:00|  女| null| null|
| 11| 李四|2012-06-06 00:00:00|  女| null| null|
| 12| 赵六|2013-06-13 00:00:00|  女| null| null|
| 13| 孙七|2014-06-01 00:00:00|  女| null| null|
+---+-----+-------------------+----+-----+-----+

4.2 没成绩显示为null

NVL(name,-1)若name为空,则返回-1,若name不为空值,则返回其自身

select stu.*,s.count,NVL(s.sum,0) as nvl from stu 
left join 
(select SId,count(DISTINCT CId) as count,sum(score) as sum 
from sc group by SId) as s 
on stu.SId = s.SId 
order by stu.SId
+---+-----+-------------------+----+-----+-----+
|SId|Sname|               Sage|Ssex|count|  nvl|
+---+-----+-------------------+----+-----+-----+
| 01| 赵雷|1990-01-01 00:00:00|  男|    3|269.0|
| 02| 钱电|1990-12-21 00:00:00|  男|    3|210.0|
| 03| 孙风|1990-12-20 00:00:00|  男|    3|240.0|
| 04| 李云|1990-12-06 00:00:00|  男|    3|100.0|
| 05| 周梅|1991-12-01 00:00:00|  女|    2|163.0|
| 06| 吴兰|1992-01-01 00:00:00|  女|    2| 65.0|
| 07| 郑竹|1989-01-01 00:00:00|  女|    2|187.0|
| 09| 张三|2017-12-20 00:00:00|  女| null|  0.0|
| 10| 李四|2017-12-25 00:00:00|  女| null|  0.0|
| 11| 李四|2012-06-06 00:00:00|  女| null|  0.0|
| 12| 赵六|2013-06-13 00:00:00|  女| null|  0.0|
| 13| 孙七|2014-06-01 00:00:00|  女| null|  0.0|
+---+-----+-------------------+----+-----+-----+

other

spark用group by 不能用 ,因为 包含了未进行分组的字段,mysql可以用*

val frame = sc.sql(
      "select SId,avg(score) from sc " +
      "group by SId " +
      "having avg(score) > 80 " +
      "order by SId")
+---+----------+
|SId|avg(score)|
+---+----------+
| 01|  89.66667|
| 05|  81.50000|
| 07|  93.50000|
+---+----------+

支持limit,在order by 后使用

val frame = sc.sql(
      "select * from sc  " +
      "order by SId "+
    "limit 1")
+---+---+-----+
|SId|CId|score|
+---+---+-----+
| 01| 01| 80.0|
+---+---+-----+

但是不支持limit分页,mysql可以

select * from SC    order by SId  limit 1,10

row_number over 完成分页
以什么分组,组内按照那个字段排名

select *,Row_Number() over (partition by SId order by score) rank from SC where SId in('01','02') order by SId
+---+---+-----+----+
|SId|CId|score|rank|
+---+---+-----+----+
| 01| 02| 90.0|   2|
| 01| 01| 80.0|   1|
| 01| 03| 99.0|   3|
| 02| 02| 60.0|   1|
| 02| 01| 70.0|   2|
| 02| 03| 80.0|   3|
+---+---+-----+----+
+---+---+-----+----+

全局的排序分页

select *,Row_Number() over ( order by score) rank from SC where SId in('01','02') order by rank
+---+---+-----+----+
|SId|CId|score|rank|
+---+---+-----+----+
| 02| 02| 60.0|   1|
| 02| 01| 70.0|   2|
| 01| 01| 80.0|   3|
| 02| 03| 80.0|   4|
| 01| 02| 90.0|   5|
| 01| 03| 99.0|   6|
+---+---+-----+----+

spark 的 like

like '8%'
但是 like '李%' 就查不到

中文字符有问题
url我是这样写的

jdbc:mysql://192.168.1.100:3306/Strengthen

要加上

?useUnicode=true&characterEncoding=utf8