mysql查询动态行转动态列,并使用mybatis执行

mysql查询动态行转动态列,并使用mybatis

新建表

# 学生表
DROP TABLE IF EXISTS students;
CREATE TABLE students(
    `id` INT(3) NOT NULL COMMENT '主键',
    `name` VARCHAR(10) NOT NULL COMMENT '姓名',
    `age` INT(3) NOT NULL COMMENT '年龄',
    `class` VARCHAR(10) NOT NULL COMMENT '班级',
    PRIMARY KEY (`id`)
);

# 成绩表
DROP TABLE IF EXISTS grade;
CREATE TABLE grade(
    `id` INT(3) NOT NULL COMMENT '主键',
    `student_id` INT(3) NOT NULL COMMENT '学生id',
    `subject` VARCHAR(20) NOT NULL COMMENT '科目',
    `grade` INT(3) NOT NULL COMMENT '成绩',
  PRIMARY KEY (`id`)
);

插入数据

# 学生表
INSERT INTO students VALUES(1, '詹溪', 18, '高三(2)班');
INSERT INTO students VALUES(2, '徐柯', 18, '高三(3)班');
INSERT INTO students VALUES(3, '蓝毅', 17, '高三(3)班');
INSERT INTO students VALUES(4, '温邱', 18, '高三(3)班');

# 成绩表
INSERT INTO grade VALUES(1, 1, "math", 98);
INSERT INTO grade VALUES(2, 1, "chinese", 72);
INSERT INTO grade VALUES(3, 1, "english", 100);
INSERT INTO grade VALUES(4, 2, "math", 92);
INSERT INTO grade VALUES(5, 2, "chinese", 95);
INSERT INTO grade VALUES(6, 2, "english", 91);
INSERT INTO grade VALUES(7, 3, "math", 86);
INSERT INTO grade VALUES(8, 3, "chinese", 80);
INSERT INTO grade VALUES(9, 3, "english", 91);
INSERT INTO grade VALUES(10, 4, "math", 95);
INSERT INTO grade VALUES(11, 4, "chinese", 92);
INSERT INTO grade VALUES(12, 4, "english", 93);

普通联合查询

SELECT s.name, s.class, g.subject, g.grade FROM students s
LEFT JOIN grade g ON s.id = g.student_id

结果
mysql查询动态行转动态列,并使用mybatis执行_第1张图片
现在需要将每个人的成绩整合成一行的多列展示。
固定列就不再赘述了,使用case...when...then或者if判断科目即可。
但如果科目不确定,或者是科目太多不想一行行写,就需要使用动态拼接的方式,生成语句。

动态行转列

# 将case...when...then或者if语句动态拼接起来。
SELECT
    @sequence :=CONCAT(@sequence,'SUM(IF(subject= "',subject,'",grade,0)) as ',subject, ',') AS sequence
FROM
    (SELECT DISTINCT subject FROM grade) g,
    (SELECT @sequence:="") s;

# 与固定列拼接成查询语句
SET @sql = CONCAT('SELECT s.name, s.class,',@sequence,' SUM(grade) as TOTAL FROM students s LEFT JOIN grade g ON s.id = g.student_id GROUP BY s.id');

# 执行sql
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;

结果
mysql查询动态行转动态列,并使用mybatis执行_第2张图片
mysql查询动态行转动态列,并使用mybatis执行_第3张图片

到此为止,成功使用sql查出想要的结果。
但是mybatis好像没有执行语句的标签。
只有selectinsertupdate等。
那么我们还是可以使用拼接语句,再塞到mybatis映射文件中去使用select标签执行。
实体没有动态字段的属性怎么办?那就使用Map类型接收结果。

使用mybatis实行动态行转列查询

Mapper.xml

    <select id="getSequence" resultType="java.lang.String">
        SELECT
            @sequence :=CONCAT(@sequence,'SUM(IF(subject= "',subject,'",grade,0)) as ',subject, ',') AS sequence
        FROM
            (SELECT DISTINCT subject FROM grade) g,
            (SELECT @sequence:="") s;
    select>

    <select id="findList" parameterType="java.lang.String" resultType="java.util.Map">
        ${sql}
    select>

Dao.java

    public List<String> getSequence();

    public List<Map<String, Object>> findList(String sql);

Service.java

    public List<Map<String, Object>> findList() {
        //获取动态拼接sql
        List<String> dynamicSequence = dao.getSequence();
        //手动与固定列拼接
        String sql = "SELECT s.name, s.class," + 
                    dynamicSequence.get(dynamicSequence.size() - 1) +
                    " SUM(grade) as TOTAL" + 
                    " FROM students s" + 
                    " LEFT JOIN grade g ON s.id = g.student_id" + 
                    " GROUP BY s.id";
        //查询结果
        List<Map<String, Object>> mapList = dao.findList(sql);
        return mapList;
    }

自此,使用mybatis实现查询行转动态列。
如果前端使用layui,可以参考我的另一篇文章layui-table动态列实现

参考资料:
mysql 行转列 列转行
mybatis 实现自定义sql

你可能感兴趣的:(mysql,mybatis)