【发布时间】:2016-05-01 08:11:51
【问题描述】:
我一直在为如何处理这种情况而苦苦挣扎:
我的表格结构如下:
Family_code | Parent_Family_Code | ....
1 2
2 4
3 6
4 3
......................
当用户搜索特定的家庭代码时,我需要返回整个路径(最多 10 级),例如对于 family_code = 1,我需要:
Family_code | parent_1 | p_2 | p_3 | p_4 | p_5 | .....
1 2 4 3 6 null null.....
我知道我可以使用sys_connect_by_path(),它会给我带来预期的结果,但它是一个字符串,而不是单独的列,这是我宁愿避免的。
这也可以通过对同一个表的 10 个左连接来完成,或者使用 LEAD()/LAG() 函数来完成,这些函数将包含很多子查询,并且会产生混乱且不可读的查询,但话又说回来,这会更多应该很重,我需要尽可能简化它。
我想出了一个使用substr()函数的解决方案(代码的长度总是varchar2(3)):
SELECT s.family_code,
s.parent_family_code_1,
s.parent_family_code_2,
CASE WHEN length(s.family_path) - (4 * 3 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 3 + 2), 3) ELSE NULL END as parent_family_code_3,
CASE WHEN length(s.family_path) - (4 * 4 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 4 + 2), 3) ELSE NULL END as parent_family_code_4,
CASE WHEN length(s.family_path) - (4 * 5 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 5 + 2), 3) ELSE NULL END as parent_family_code_5,
CASE WHEN length(s.family_path) - (4 * 6 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 6 + 2), 3) ELSE NULL END as parent_family_code_6,
CASE WHEN length(s.family_path) - (4 * 7 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 7 + 2), 3) ELSE NULL END as parent_family_code_7,
CASE WHEN length(s.family_path) - (4 * 8 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 8 + 2), 3) ELSE NULL END as parent_family_code_8,
CASE WHEN length(s.family_path) - (4 * 9 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 9 + 2), 3) ELSE NULL END as parent_family_code_9,
CASE WHEN length(s.family_path) - (4 * 10 + 2) > 0 THEN substr(s.family_path, length(s.family_path) - (4 * 10 + 2), 3) ELSE NULL END as parent_family_code_10
FROM (SELECT t.family_code,
t.parent_family_code as parent_family_code_1,
prior t.parent_family_code as parent_family_code_2,
sys_connect_by_path(t.family_code, ',') as family_path
FROM table t
connect by prior t.family_code = t.parent_family_code) s
但我想要一个不使用子字符串的解决方案,因为当其他开发人员接触它时,对其进行任何维护将变得更加困难 . 所以基本上我的问题是 - 如何在不使用子字符串的情况下将整个路径选择为不同的列?
【问题讨论】:
-
您在问题中编辑的代码不起作用 - 如果您还
SELECT family_path那么您会看到 (a) 它没有获取整个路径并且 (b) 路径不是全部由子字符串处理,因为您有可变长度的字符串并使用固定长度的条件。 -
如果你想要整个路径,那么你可以使用
sys_connect_by_path(t.parent_family_code, ',') || ',' || t.family_code as family_path,但它仍然不能解决case条件下可变长度数据和固定长度的第二个问题。