今天遇到一个问题,以前都是使用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;
}
虽然结果是可行的,但是我觉得我的方式太麻烦了,不知道大家有没有更好的办法?我想到用递归,但是我不知道该怎么写这个递归。希望大家帮帮我。