项目中一个有关数据分类的问题?
发布于 10 年前 作者 xiuxu123 3455 次浏览 最后一次编辑是 8 年前

今天遇到一个问题,以前都是使用oracle数据库这个问题直接在oracle中就解决了,但是现在是在mysql中没有办法使用迭代查询,所以就要自己写代码解决,我的问题是:

数据表中有这样一组种子数据:

id       name       pid
1        AA          0
2        BB          0
3        CC          0
4        DD          1
5        EE          1
6        FF          2
7        GG          3
8        H           3
9        II          3
10       JJ          2
....  

数据量不大才几十条,

我是用nodejs开发的,所以从数据库读出来之后是一组对象数组,这样的

[obj1, obj2, obj3, obj4................]

这里的obj里的形式是{id:1, name:'AA', pid:0, mark:'Y'}(这里的mark字段是我自己加的,为了方便我后面的程序操作)。我要的结果就是把这个数组变成一个2维的数组,数组里面的每一项都是一个父类和他相应的子类(父类在第一个位置),这样的:

[[obj1, obj2, obj3], [obj4, obj5..],.... [obj11, obj12,...]]

其实如果在oracle数据库的话,直接在数据库方面就搞定了,但是mysql不行,除非要写存储过程太麻烦。

我的思路是,先从第一个的pid开始,依次查找和他相同pid的obj或者id和pid相同的obj,找到之后标记下,然后放到临时数组里面,当第一次遍历完成之后,把临时数组放到数组里面,然后在清除标记的项,然后剩下的再次进入循环。下面是我的实现方法:

function change(temp){
    //存放结果的数组
    var arr = new Array();

    //外围循环控制数组数量
    for(var i=0, x=0;i<temp.length;i++){

        //临时数组存放每个单个数组项
        var temparr = new Array();

        //查找相同对象并且标记
        for(var j=x+1;j<temp.length;j++){

            //如果是父类就放到第一个位置
            if(temp[x].pid == temp[j].id){
                temparr.unshift(temp[j]);

                //标记这个项是处理过的
                temp[j].mark = 'D';
            }

            
            //如果是子类就放第一个的后面
            if(temp[x].pid == temp[j].pid && temp[j].pid != 0){
                temparr[temparr.length] = temp[j];

                temp[j].mark = 'D';
            }

            //本身也要放进数组
            if(j == temp.length-1){
                temparr[temparr.length] = temp[x];

                temp[x].mark = 'D';
            }
        }

        //查找到的结果放到结果数组里
        arr[arr.length] = temparr;

        //清除标记的对象
        for(var z=0, k=0;z<temp.length;z++){
            //判断前一个是否已经删除
            if(k==0){
                z=0;
            }

            //如果是标记过的就删除
            if(temp[z].mark == 'D'){
                //这里没有多余,这个属性也用不着
                delete temp[z].mark;

                //清除标记过的项
                temp.splice(z, 1);

                //归零,方便下次从0开始
                k=0;

                //继续操作
                continue;
            }else{
                //如果没有标记就累加,用于跳过
                k++;
            }
        }
    }

    return arr;
}

虽然结果是可行的,但是我觉得我的方式太麻烦了,不知道大家有没有更好的办法?我想到用递归,但是我不知道该怎么写这个递归。希望大家帮帮我。

2 回复

这个…感觉数据库不支持递归查询的话,服务端做好蛋疼啊。 要不重新设计一下数据结构,用空间换时间??

呵呵,你真逗!

回到顶部