mysql递归自联接

时间:2010-08-11 10:59:21

标签: mysql recursion self-join

create table test(
container varchar(1),
contained varchar(1)
);

insert into test values('X','A');
insert into test values('X','B');
insert into test values('X','C');
insert into test values('Y','D');
insert into test values('Y','E');
insert into test values('Y','F');
insert into test values('A','P');
insert into test values('P','Q');
insert into test values('Q','R');
insert into test values('R','Y');
insert into test values('Y','X');

select * from test;

    mysql> select * from test;
    +-----------+-----------+
    | container | contained |
    +-----------+-----------+
    | X         | A         |
    | X         | B         |
    | X         | C         |
    | Y         | D         |
    | Y         | E         |
    | Y         | F         |
    | A         | P         |
    | P         | Q         |
    | Q         | R         |
    | R         | Y         |
    | Y         | X         |
    +-----------+-----------+
    11 rows in set (0.00 sec)

我可以使用单个自加入找出“X”下包含的所有distinct值吗?

EDIT

喜欢,在这里 X包含A,B和C. A包含P. P包含Q. Q包含R. R包含Y. Y包含C,D和E ......

所以当我查询X时,我想显示A,B,C,D,E,P,Q,R,Y。

EDIT

通过编程做到了。

package com.catgen.helper;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.ArrayList;
import java.util.List;

import com.catgen.factories.Nm2NmFactory;

public class Nm2NmHelper {
    private List<String> fetched;
    private List<String> fresh;

    public List<String> findAllContainedNMByMarketId(Connection conn, String marketId) throws SQLException{
        fetched = new ArrayList<String>();
        fresh = new ArrayList<String>();
        fresh.add(marketId.toLowerCase());
        while(fresh.size()>0){
            fetched.add(fresh.get(0).toLowerCase());
            fresh.remove(0);
            List<String> tempList = Nm2NmFactory.getContainedNmByContainerNm(conn, fetched.get(fetched.size()-1));
            if(tempList!=null){
                for(int i=0;i<tempList.size();i++){
                    String current = tempList.get(i).toLowerCase();
                    if(!fetched.contains(current) && !fresh.contains(current)){
                        fresh.add(current);
                    }
                }
            }
        }
        return fetched;
    }
}

虽然不是同一个表和字段。但我希望你能得到这个概念。 谢谢你们。

2 个答案:

答案 0 :(得分:7)

使用与该数据结构的单个连接,无法递归获取所有包含的对象。你需要一个递归查询,但MySQL还不支持。

然而,你可以构造一个闭包表,然后你可以用一个简单的查询来完成它。有关详细信息和其他方法(例如,嵌套集),请参阅Bill Karwin的幻灯片Models for heirarchical data。幻灯片69比较了不同的设计,以便于实现“查询子树”。您选择的设计(邻接列表)是此类查询的所有四种设计中最尴尬的。

答案 1 :(得分:0)

如何将整个表读入php数组,并确定子进程。一个会自称的功能?

但如果表格超过10000行,这不是一个好的解决方案...