在项目中,有类似如下数据集:
A_Port Z_Port
1 2
3 2
3 4
4 5
3 1
4 1
A_Port和Z_Port是一种连接关系,在上面的数据中,以前四条为例,表示的是1和2相连,3和2相连,3和3相连,4和5相连。
但在该数据库的设计中,却并不是一种的标准的树形关系,因此不能用标准的Connect BY Prior Z_Port = A_Port查询,
例如我要查找1-5的路径,却是A-Z-Z-A-A-Z-A-Z。
现在请大家帮忙,我要查找1-5的所有路径,在该示例中,明显看出有3条,1-2-3-4-5,1-3-4-5,1-4-5,如何写。
我也曾经考虑过将该数据集反向,但是在9i中,不支持NoCyCle,请大家帮忙啦。
A_Port Z_Port
1 2
3 2
3 4
4 5
3 1
4 1
A_Port和Z_Port是一种连接关系,在上面的数据中,以前四条为例,表示的是1和2相连,3和2相连,3和3相连,4和5相连。
但在该数据库的设计中,却并不是一种的标准的树形关系,因此不能用标准的Connect BY Prior Z_Port = A_Port查询,
例如我要查找1-5的路径,却是A-Z-Z-A-A-Z-A-Z。
现在请大家帮忙,我要查找1-5的所有路径,在该示例中,明显看出有3条,1-2-3-4-5,1-3-4-5,1-4-5,如何写。
我也曾经考虑过将该数据集反向,但是在9i中,不支持NoCyCle,请大家帮忙啦。
SQL> SELECT * FROM TEST_NO_TREE; A_PORT Z_PORT
---------- ----------
1 2
3 2
3 4
4 5
3 1
4 16 rows selectedSQL> SELECT LTRIM(MAX(SYS_CONNECT_BY_PATH(RIGHTS, '-')), '-') ROADS
2 FROM (SELECT TN.*,
3 DECODE(SIGN(Z_PORT - A_PORT), 1, Z_PORT, A_PORT) LEFTS,
4 DECODE(SIGN(Z_PORT - A_PORT), 1, A_PORT, Z_PORT) RIGHTS
5 FROM TEST_NO_TREE TN) TT
6 GROUP BY (ROWNUM - LEVEL)
7 START WITH RIGHTS = 1
8 CONNECT BY PRIOR LEFTS = RIGHTS;ROADS
--------------------------------------------------------------------------------
1-2-3-4-5
1-3-4-5
1-4-5
SQL> SELECT LTRIM(MAX(SYS_CONNECT_BY_PATH(DECODE(SIGN(Z_PORT - A_PORT),
2 1,
3 A_PORT,
4 Z_PORT),
5 '-')),
6 '-') ROADS
7 FROM TEST_NO_TREE TT
8 GROUP BY (ROWNUM - LEVEL)
9 START WITH DECODE(SIGN(Z_PORT - A_PORT), 1, A_PORT, Z_PORT) = 1
10 CONNECT BY PRIOR DECODE(SIGN(Z_PORT - A_PORT), 1, Z_PORT, A_PORT) =
11 DECODE(SIGN(Z_PORT - A_PORT), 1, A_PORT, Z_PORT);ROADS
--------------------------------------------------------------------------------
1-2-3-4-5
1-3-4-5
1-4-5
老兄的方法妙绝,但有两个问题:
1.在我的机器上执行是1-2-3-4,1-3-4,1-4 ,不过看得出,结果是对的。
2.老兄很巧妙地解决了A_Port和Z_Port交换的问题,该交换的才交换,但我的实际项目中,A_Port和Z_Port是varchar2(32),生成并无规律。
希望老兄不吝赐教。
思路应该是没错的。我测试了很多数据,每到最后一位的时候数据就出不来。
1: 我的思路是不是树让它变成树,这样就可以用CONNECT BY解决了。思路应该是对的。
2: 我的想法是先插入的记录会比较小,所以是先有父在有子,因此通过比较大小来判断父子关系的。如果没有规律就让他变成有规律的。这只是对于现在这种情况,你可以参考一下。