Oracle 树上的逻辑
Logic on Oracle Tree
下面是 table 的结构:
REF_ID NOT NULL NUMBER
REF_TYPE_ID NOT NULL NUMBER
PARENT_REF_ID NUMBER
REF_VALUE 不是 NULL VARCHAR2(255)
以下查询取得了以下结果,但我可能需要结果:
WITH
refs (ref_id,
ref_type_id,
parent_ref_id,
ref_value)
AS
(SELECT 501, 1, NULL, 207 FROM DUAL
UNION ALL
SELECT 502, 2, 501, 4 FROM DUAL
UNION ALL
SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
TRIM (
',' FROM
SYS_CONNECT_BY_PATH (
CASE r.ref_type_id
WHEN 1 THEN 'article '
WHEN 2 THEN 'par '
WHEN 3 THEN '('
WHEN 4 THEN 'point '
WHEN 5 THEN 'sous '
WHEN 6 THEN NULL
WHEN 8 THEN NULL
ELSE '/'
END
|| r.ref_id,
',')) AS ref_label
FROM refs r
WHERE CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR r.parent_ref_id = r.ref_id;
查询输出:
STARTING_REF_ID REF_LABEL
501 article 501
502 par 502,article 501
503 (503,par 502,article 501
预期结果:
STARTING_REF_ID REF_LABEL
501 article 501
502 article 501,par 502
503 article 501,par 502,(503,
向 select
添加反向
WITH
refs (ref_id,
ref_type_id,
parent_ref_id,
ref_value)
AS
(SELECT 501, 1, NULL, 207 FROM DUAL
UNION ALL
SELECT 502, 2, 501, 4 FROM DUAL
UNION ALL
SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
TRIM (
',' FROM
reverse( --reverse path order (also reverts letters in words)
SYS_CONNECT_BY_PATH (
reverse( --put letters in words and numbers in ids back in the right order
CASE r.ref_type_id
WHEN 1 THEN 'article '
WHEN 2 THEN 'par '
WHEN 3 THEN '('
WHEN 4 THEN 'point '
WHEN 5 THEN 'sous '
WHEN 6 THEN NULL
WHEN 8 THEN NULL
ELSE '/'
END
|| r.ref_id),
',')
) ) AS ref_label
FROM refs r
WHERE CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR r.parent_ref_id = r.ref_id
你做这一切的方式很不自然。
您应该从根目录(父 ID 为 null
)开始,然后从它开始“向下”,而不是相反。那么你不需要where
子句,你需要一个start with
子句;而 connect by
条件必须相反。然后您不需要对查询进行任何其他更改。
像这样:
WITH
refs (ref_id,
ref_type_id,
parent_ref_id,
ref_value)
AS
(SELECT 501, 1, NULL, 207 FROM DUAL
UNION ALL
SELECT 502, 2, 501, 4 FROM DUAL
UNION ALL
SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
TRIM (
',' FROM
SYS_CONNECT_BY_PATH (
CASE r.ref_type_id
WHEN 1 THEN 'article '
WHEN 2 THEN 'par '
WHEN 3 THEN '('
WHEN 4 THEN 'point '
WHEN 5 THEN 'sous '
WHEN 6 THEN NULL
WHEN 8 THEN NULL
ELSE '/'
END
|| r.ref_id,
',')) AS ref_label
FROM refs r
START WITH parent_ref_id is null
CONNECT BY PRIOR ref_id = parent_ref_id;
下面是 table 的结构:
REF_ID NOT NULL NUMBER
REF_TYPE_ID NOT NULL NUMBER
PARENT_REF_ID NUMBER
REF_VALUE 不是 NULL VARCHAR2(255)
以下查询取得了以下结果,但我可能需要结果:
WITH
refs (ref_id,
ref_type_id,
parent_ref_id,
ref_value)
AS
(SELECT 501, 1, NULL, 207 FROM DUAL
UNION ALL
SELECT 502, 2, 501, 4 FROM DUAL
UNION ALL
SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
TRIM (
',' FROM
SYS_CONNECT_BY_PATH (
CASE r.ref_type_id
WHEN 1 THEN 'article '
WHEN 2 THEN 'par '
WHEN 3 THEN '('
WHEN 4 THEN 'point '
WHEN 5 THEN 'sous '
WHEN 6 THEN NULL
WHEN 8 THEN NULL
ELSE '/'
END
|| r.ref_id,
',')) AS ref_label
FROM refs r
WHERE CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR r.parent_ref_id = r.ref_id;
查询输出:
STARTING_REF_ID REF_LABEL
501 article 501
502 par 502,article 501
503 (503,par 502,article 501
预期结果:
STARTING_REF_ID REF_LABEL
501 article 501
502 article 501,par 502
503 article 501,par 502,(503,
向 select
添加反向WITH
refs (ref_id,
ref_type_id,
parent_ref_id,
ref_value)
AS
(SELECT 501, 1, NULL, 207 FROM DUAL
UNION ALL
SELECT 502, 2, 501, 4 FROM DUAL
UNION ALL
SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
TRIM (
',' FROM
reverse( --reverse path order (also reverts letters in words)
SYS_CONNECT_BY_PATH (
reverse( --put letters in words and numbers in ids back in the right order
CASE r.ref_type_id
WHEN 1 THEN 'article '
WHEN 2 THEN 'par '
WHEN 3 THEN '('
WHEN 4 THEN 'point '
WHEN 5 THEN 'sous '
WHEN 6 THEN NULL
WHEN 8 THEN NULL
ELSE '/'
END
|| r.ref_id),
',')
) ) AS ref_label
FROM refs r
WHERE CONNECT_BY_ISLEAF = 1
CONNECT BY PRIOR r.parent_ref_id = r.ref_id
你做这一切的方式很不自然。
您应该从根目录(父 ID 为 null
)开始,然后从它开始“向下”,而不是相反。那么你不需要where
子句,你需要一个start with
子句;而 connect by
条件必须相反。然后您不需要对查询进行任何其他更改。
像这样:
WITH
refs (ref_id,
ref_type_id,
parent_ref_id,
ref_value)
AS
(SELECT 501, 1, NULL, 207 FROM DUAL
UNION ALL
SELECT 502, 2, 501, 4 FROM DUAL
UNION ALL
SELECT 503, 3, 502, 1 FROM DUAL)
SELECT CONNECT_BY_ROOT r.ref_id as starting_ref_id,
TRIM (
',' FROM
SYS_CONNECT_BY_PATH (
CASE r.ref_type_id
WHEN 1 THEN 'article '
WHEN 2 THEN 'par '
WHEN 3 THEN '('
WHEN 4 THEN 'point '
WHEN 5 THEN 'sous '
WHEN 6 THEN NULL
WHEN 8 THEN NULL
ELSE '/'
END
|| r.ref_id,
',')) AS ref_label
FROM refs r
START WITH parent_ref_id is null
CONNECT BY PRIOR ref_id = parent_ref_id;