create table treeT(ID primary key,OyaID) as
select 1, 0 from dual union
select 2, 1 from dual union
select 3, 2 from dual union
select 4, 3 from dual union
select 5, 1 from dual union
select 6, 5 from dual union
select 7, 6 from dual union
select 8, 7 from dual union
select 9, 7 from dual union
select 10, 8 from dual union
select 11, 8 from dual union
select 12, 8 from dual union
select 13,11 from dual
select ID,OyaID,Level,Connect_by_is_leaf,
sys_connect_by_path(to_char(ID),',') as path
from treeT
Start With OyaID = 0
connect by prior ID = OyaID;
Oracleの階層問い合わせを、スタックを使った深さ優先探索で実装する。
public final class hire1 {
//ノード
class NodeDef {
int ID;
int OyaID;
NodeDef(int pID,int pOyaID){
ID = pID;
OyaID = pOyaID;
}
int LV=1; //Level用
int isLeaf=1; //isleaf用
String Path; //sys_connect_by_path用
void PrintOut(){
System.out.println("ID=" + Integer.toString(ID)
+ ",OyaID=" + Integer.toString(OyaID)
+ ",Level=" + Integer.toString(LV)
+ ",isLeaf=" + Integer.toString(isLeaf)
+ ",path=" + Path);
}
};
//スタック
class StackClass {
int stackP;
NodeDef stackValue[];
StackClass(){
stackP = 0;
stackValue = new NodeDef[200];
}
private void push(NodeDef pNodeDef){
stackValue[stackP++] = pNodeDef;
//System.out.println("pushValue is " + Integer.toString(pNodeDef.ID));
}
private NodeDef pop(){
//System.out.println("popValue is " + Integer.toString(stackValue[stackP-1].ID));
return stackValue[--stackP];
}
boolean isEmpty(){
return stackP == 0;
}
}
//対象データ
NodeDef TargetData[] = new NodeDef[13];
public static void main(String[] args) {
hire1 mi = new hire1();
mi.main();
}
void main() {
TargetData[0] = new NodeDef( 1, 0);
TargetData[1] = new NodeDef( 2, 1);
TargetData[2] = new NodeDef( 3, 2);
TargetData[3] = new NodeDef( 4, 3);
TargetData[4] = new NodeDef( 5, 1);
TargetData[5] = new NodeDef( 6, 5);
TargetData[6] = new NodeDef( 7, 6);
TargetData[7] = new NodeDef( 8, 7);
TargetData[8] = new NodeDef( 9, 7);
TargetData[9] = new NodeDef(10, 8);
TargetData[10] = new NodeDef(11, 8);
TargetData[11] = new NodeDef(12, 8);
TargetData[12] = new NodeDef(13,11);
int UPB = TargetData.length-1;
StackClass st = new StackClass();
//Start withの条件を満たす行を探す
for (int i=0;i<=UPB;i++){
//start with句を満たしたらpushして階層問い合わせ
if (TargetData[i].OyaID == 0){
TargetData[i].Path = Integer.toString(TargetData[i].ID);
st.push(TargetData[i]);
int LoopChk = 0;
while (st.isEmpty() == false){
NodeDef priNode = st.pop();
for(int K=UPB;K>=0;K--){
if (priNode.ID == TargetData[K].OyaID){ //connect by句
TargetData[K].LV = priNode.LV+1;
TargetData[K].Path = priNode.Path + "-" + Integer.toString(TargetData[K].ID);
for (int L=0;L<=UPB;L++)
if (TargetData[L].ID == priNode.ID) //主キーでpriorデータを探索しIsLeafを0に
TargetData[L].isLeaf = 0;
st.push(TargetData[K]);
}
}
priNode.PrintOut();
}
if (++LoopChk == 100){
System.out.println("There is a Loop."); break;
}
}
//階層問い合わせ後の、初期化処理
for (int J=0;J<=UPB;J++){
TargetData[J].LV=1;
TargetData[J].Path="";
TargetData[J].isLeaf=1;
}
}
}
}
ID=1,OyaID=0,Level=1,isLeaf=0,path=1
ID=2,OyaID=1,Level=2,isLeaf=0,path=1-2
ID=3,OyaID=2,Level=3,isLeaf=0,path=1-2-3
ID=4,OyaID=3,Level=4,isLeaf=1,path=1-2-3-4
ID=5,OyaID=1,Level=2,isLeaf=0,path=1-5
ID=6,OyaID=5,Level=3,isLeaf=0,path=1-5-6
ID=7,OyaID=6,Level=4,isLeaf=0,path=1-5-6-7
ID=8,OyaID=7,Level=5,isLeaf=0,path=1-5-6-7-8
ID=10,OyaID=8,Level=6,isLeaf=1,path=1-5-6-7-8-10
ID=11,OyaID=8,Level=6,isLeaf=0,path=1-5-6-7-8-11
ID=13,OyaID=11,Level=7,isLeaf=1,path=1-5-6-7-8-11-13
ID=12,OyaID=8,Level=6,isLeaf=1,path=1-5-6-7-8-12
ID=9,OyaID=7,Level=5,isLeaf=1,path=1-5-6-7-9