前言

首先说明一下场景啊,今天遇到个业务问题,就是通过一个主表,关联另一个表,主表中一条数据,关联出另外一张表多条数据,导致主表也生成了多条重复数据。但我页面展示的时候不希望展示出重复数据。这是我们的业务需求,现在我们来看看有多少方法来解决这个问题。
注:这块可不是数组去重,关于集合数组去重的方法参考
在这里插入图片描述

在这里插入图片描述

为了便于理解,我先把模拟一下数据。

SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;

-- ----------------------------
-- Table structure for student
-- ----------------------------
DROP TABLE IF EXISTS `student`;
CREATE TABLE `student`  (
  `id` int(0) NOT NULL,
  `equalDate1` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `equalDate2` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `equalDate3` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `name` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL,
  `age` int(0) NULL DEFAULT NULL,
  PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB CHARACTER SET = utf8mb4 COLLATE = utf8mb4_0900_ai_ci ROW_FORMAT = Dynamic;

-- ----------------------------
-- Records of student
-- ----------------------------
INSERT INTO `student` VALUES (1, '相同数据1', '相同数据2', '相同数据3', '张三', 10);
INSERT INTO `student` VALUES (2, '相同数据1', '相同数据2', '相同数据3', '李四', 12);
INSERT INTO `student` VALUES (3, '相同数据1', '相同数据2', '相同数据3', '王五', 10);
INSERT INTO `student` VALUES (4, '相同数据1', '相同数据2', '相同数据3', '王麻子', 10);
INSERT INTO `student` VALUES (5, '相同数据11', '相同数据21', '相同数据31', '张三1', 10);
INSERT INTO `student` VALUES (6, '相同数据11', '相同数据21', '相同数据31', '张三2', 10);

SET FOREIGN_KEY_CHECKS = 1;



CREATE TABLE `student` (
  `id` int NOT NULL,
  `equalDate1` varchar(20) DEFAULT NULL,
  `equalDate2` varchar(255) DEFAULT NULL,
  `equalDate3` varchar(20) DEFAULT NULL,
  `name` varchar(20) DEFAULT NULL,
  `age` int(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

select * from student;
INSERT INTO student (id,equalDate1,equalDate2,equalDate3,`name`,age)
VALUES(1,"相同数据1", "相同数据2", "相同数据3","张三",10),
(2,"相同数据1", "相同数据2", "相同数据3","李四",12),
(3,"相同数据1", "相同数据2", "相同数据3","王五",10),
(4,"相同数据1", "相同数据2", "相同数据3","王麻子",10),
(5,"相同数据11", "相同数据21", "相同数据31","张三1",10),
(6,"相同数据11", "相同数据21", "相同数据31","张三2",10)

select equalDate1,equalDate2,equalDate3
,GROUP_CONCAT(`name`)as nameList,GROUP_CONCAT(`age`)as ageList
 from student GROUP BY equalDate1,equalDate2,equalDate3
				   

CREATE TABLE `studentleft` (
  `id` int NOT NULL,
  `tableid` int NOT NULL,
  `name` varchar(20) DEFAULT NULL,
  `age` int(4) DEFAULT NULL,
  PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8mb4 COLLATE=utf8mb4_0900_ai_ci;

select * from studentleft;
INSERT INTO studentleft (id,tableid,`name`,age)
VALUES(1,1, "张三",10),
(2,1,"李四",12),
(3,1,"王五",10),
(4,1,"王麻子",10),
(5,2,"张三1",10),
(6,2,"张三2",10)

select s.equalDate1,s.equalDate2,s.equalDate3  from student s  where s.tableid = 1;
select l.`name`,l.age from  studentleft l where l.tableid = 1;
select s.equalDate1,s.equalDate2,s.equalDate3,l.`name`,l.age
 from student s ,studentleft l where s.tableid = l.tableid and s.tableid = 1

实现功能 主表一条数据关联后产生多条数据,现在就想要展示一条数据。
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
我们先说笨办法 list、map 方法。现实实现不建议这么玩,这里只是学习一下思维,这块还折腾了我前后4个来小时,还是记录一下编码过程
这块我没有连接数据库查,我就模仿了一下查到的集合数

package test;

import java.util.List;

/**
 * @version: V1.0
 * @author: p
 * @description:
 * @date:2022/4/1
 */
public class Student {
    //这样相同数据 就展示一条 (把多条年龄、姓名用List接收)
    public String equalDate1;//相同数据
    public String equalDate2;//相同数据
    public String equalDate3;//相同数据
    public String name;
    public int age;
    public String stringAge;
    public List ageList; //存放年龄集合
    public List nameList; //拿到姓名集合

    public Student() {

    }

    public Student(String equalDate1, String equalDate2, String equalDate3, String name, int age) {
        this.equalDate1 = equalDate1;
        this.equalDate2 = equalDate2;
        this.equalDate3 = equalDate3;
        this.name = name;
        this.age = age;
    }

    public Student(String equalDate1, String equalDate2, String equalDate3, String name,String stringAge) {
        this.equalDate1 = equalDate1;
        this.equalDate2 = equalDate2;
        this.equalDate3 = equalDate3;
        this.name = name;
        this.stringAge = stringAge;

    }

    public String getStringAge() {
        return stringAge;
    }

    public void setStringAge(String stringAge) {
        this.stringAge = stringAge;
    }

    public String getEqualDate1() {
        return equalDate1;
    }

    public void setEqualDate1(String equalDate1) {
        this.equalDate1 = equalDate1;
    }

    public String getEqualDate2() {
        return equalDate2;
    }

    public void setEqualDate2(String equalDate2) {
        this.equalDate2 = equalDate2;
    }

    public String getEqualDate3() {
        return equalDate3;
    }

    public void setEqualDate3(String equalDate3) {
        this.equalDate3 = equalDate3;
    }

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }

    public int getAge() {
        return age;
    }

    public void setAge(int age) {
        this.age = age;
    }

    public List getAgeList() {
        return ageList;
    }

    public void setAgeList(List ageList) {
        this.ageList = ageList;
    }

    public List getNameList() {
        return nameList;
    }

    public void setNameList(List nameList) {
        this.nameList = nameList;
    }
}

方法一: List 不建议使用

package test;

import java.util.ArrayList;
import java.util.List;

/**
 * @version: V1.0
 * @author: p
 * @description:
 * @date:2022/4/1
 */
public class TestCollByList {
    public static void main(String[] args) {
        //合并相同数据之 使用  list实现
        //下面是模拟合并 代码调试了3个来小时,注意旗帜判断 跟 i-- 以及最后在保存一次 不容有失
        Student student1 = new Student("相同数据1", "相同数据2", "相同数据3", "张三", 10);
        Student student2 = new Student("相同数据1", "相同数据2", "相同数据3", "李四", 12);
        Student student3 = new Student("相同数据1", "相同数据2", "相同数据3", "王五", 10);
        Student student4 = new Student("相同数据1", "相同数据2", "相同数据3", "王麻子", 10);
        Student student5 = new Student("相同数据11", "相同数据21", "相同数据31", "张三1", 10);
        Student student6 = new Student("相同数据11", "相同数据21", "相同数据31", "张三2", 10);
        //首先说明一下  前三个数据是一致的 不一致的只是后面2个 像上面6条数据 按照我们需求其实就两条数据 ,
        // 也就是我们要合并前3项的结果为一条,后面两条变成一个两个List返回  也是我们的需求
        List<Student> studentList = new ArrayList<>();
        List<Student> studentListNew = new ArrayList<>();
        studentList.add(student1);
        studentList.add(student2);
        studentList.add(student3);
        studentList.add(student4);
        studentList.add(student5);
        studentList.add(student6);
        String flag = "";
        List listName = new ArrayList();
        List listAge = new ArrayList();
        int size = studentList.size();
        for (int i = 0; i < size; i++) {
            if (i == 0) {
                flag = studentList.get(0).getEqualDate1();
            }

            //String falgType = studentList.get(i).getEqualDate1();
            if (flag.equals(studentList.get(i).getEqualDate1())) {

                listAge.add(studentList.get(i).getAge());
                listName.add(studentList.get(i).getName());
                //这里也必须放个旗帜判断
                flag = studentList.get(i).getEqualDate1();
            } else {
                Student student = new Student();
                student.setEqualDate1(studentList.get(i - 1).getEqualDate1());
                student.setEqualDate2(studentList.get(i - 1).getEqualDate2());
                student.setEqualDate3(studentList.get(i - 1).getEqualDate3());
                student.setAgeList(listAge);
                student.setNameList(listName);
                studentListNew.add(student);
                //下面必须清空上次保留的历史信息
                listName = new ArrayList();
                listAge = new ArrayList();
                //这个旗帜判断必须放这里不被下面 i--影响
                flag = studentList.get(i).getEqualDate1();
                i--;//这步很关键,因为走else 就走不了if i又在自增,你满足if时就少一条
            }
            //这个是最后一步保存下来,
            if (i == size-1) {
                Student student = new Student();
                student.setEqualDate1(studentList.get(i - 1).getEqualDate1());
                student.setEqualDate2(studentList.get(i - 1).getEqualDate2());
                student.setEqualDate3(studentList.get(i - 1).getEqualDate3());
                student.setAgeList(listAge);
                student.setNameList(listName);
                studentListNew.add(student);
            }
        }


    }
}

方法二: Map 不建议使用

package test;

import java.util.ArrayList;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

/**
 * @version: V1.0
 * @author: p
 * @description:
 * @date:2022/4/1
 */
public class TestCollByMap {
    public static void main(String[] args) {
        //合并相同数据之 使用  Map实现   map特点 同key覆盖  跟list逻辑一样

        Student student1 = new Student("相同数据1", "相同数据2", "相同数据3", "张三", 10);
        Student student2 = new Student("相同数据1", "相同数据2", "相同数据3", "李四", 12);
        Student student3 = new Student("相同数据1", "相同数据2", "相同数据3", "王五", 10);
        Student student4 = new Student("相同数据1", "相同数据2", "相同数据3", "王麻子", 10);
        Student student5 = new Student("相同数据11", "相同数据21", "相同数据31", "张三1", 10);
        Student student6 = new Student("相同数据11", "相同数据21", "相同数据31", "张三2", 10);
        //首先说明一下  前三个数据是一致的 不一致的只是后面2个 像上面6条数据 按照我们需求其实就两条数据 ,
        // 也就是我们要合并前3项的结果为一条,后面两条变成一个两个List返回  也是我们的需求
        List<Student> studentList = new ArrayList<>();
        Map map = new LinkedHashMap();//有序,保留原有顺序
        List<Map> all = new ArrayList<>();
        studentList.add(student1);
        studentList.add(student2);
        studentList.add(student3);
        studentList.add(student4);
        studentList.add(student5);
        studentList.add(student6);
        String flag = "";
        List listName = new ArrayList();
        List listAge = new ArrayList();
        int size = studentList.size();
        for (int i = 0; i < size; i++) {
            if (i == 0) {
                flag = studentList.get(0).getEqualDate1();
            }
            if (flag.equals(studentList.get(i).getEqualDate1())) {

                listAge.add(studentList.get(i).getAge());
                listName.add(studentList.get(i).getName());
                //这里也必须放个旗帜判断
                flag = studentList.get(i).getEqualDate1();
                map.put("equalDate1",studentList.get(i).getEqualDate1());
                map.put("equalDate2",studentList.get(i).getEqualDate2());
                map.put("equalDate3",studentList.get(i).getEqualDate3());
                map.put("ageList",listAge);
                map.put("nameList",listName);
            } else {
                //下面必须清空上次保留的历史信息
                listName = new ArrayList();
                listAge = new ArrayList();
                all.add(map);
                map = new LinkedHashMap();//todo 防止同名覆盖问题  很关键
                //这个旗帜判断必须放这里不被下面 i--影响
                flag = studentList.get(i).getEqualDate1();
                i--;//这步很关键,因为走else 就走不了if i又在自增,你满足if时就少一条
            }
            //这个是最后一步保存下来,
            if (i == size-1) {
                all.add(map);
            }
        }

    }
}


方法三: sql实现 最简单 不用动脑、推荐使用

在这里插入图片描述

package test;

import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;

/**
 * @version: V1.0
 * @author: p
 * @description:
 * @date:2022/4/1
 */
public class TestCollBySql {
    public static void main(String[] args) {
        //合并相同数据之 使用  sql实现   最简单 不用动脑
        //我们通过sql中的 group_concat()函数,把数据直接干到一条, 把姓名,年龄 用,分割
        //现在如果说前端来处理的话后端已经完事了,如果前端不想处理,让我们反对应的list
        Student student1 = new Student("相同数据1", "相同数据2", "相同数据3", "张三,李四,王五,王麻子", "10,12,10,10");
        Student student5 = new Student("相同数据11", "相同数据21", "相同数据31", "张三1,张三2", "10,10");
        //首先说明一下  前三个数据是一致的 不一致的只是后面2个 像上面6条数据 按照我们需求其实就两条数据 ,
        // 也就是我们要合并前3项的结果为一条,后面两条变成一个两个List返回  也是我们的需求
        List<Student> studentList = new ArrayList<>();

        studentList.add(student1);
        studentList.add(student5);

        for (Student student : studentList) {
            String[] splitAge = student.getStringAge().split(",");
            String[] splitName = student.getName().split(",");

            student.setNameList(Arrays.asList(splitName));
            student.setAgeList(Arrays.asList(splitAge));
        }
        System.out.println(studentList);
    }

}

方法四,推荐使用

这块我不在再写具体操作,因为我就是用这个解决问题的,现在时间也很晚了就不再写了。

思想:我们两张表分开查,我们查出主表所有数据,我们前面说过,主表数据是不重复的,通过主表关联id去查另外一张表,查出它的集合,然后在 主表定义对应的list字段 来接受查出来的list。可能光这么描述看不太懂,我随后赋个截图吧。

select s.equalDate1,s.equalDate2,s.equalDate3  
from student s  where s.tableid = 1;


select l.`name`,l.age from  studentleft l where l.tableid = 1;

在这里插入图片描述

一条数据拆分多条数据

(正常来说我们查出来的数据就是多条的,不需要做处理就是一对多)
既然有多对一,就有一对多,比如导出数据的时候,我就需要把你合并为1条的数据拆分好几条,然后再利用表格合并相同数据。

这块方法也很多,我就不 一 一 列举了,

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

上面这么写返回的参数形式有些恶心,进行如下优化
其实也不是多么恶心,只不过是都放在一个类中的对应list里,无伤大雅
在这里插入图片描述

同样是返回两条数据,这么看起来层次感就很好
在这里插入图片描述

Logo

为开发者提供学习成长、分享交流、生态实践、资源工具等服务,帮助开发者快速成长。

更多推荐