Sql Oracle-多级自然排序行
使用Oracle 10.2.0 我有一个由行号、缩进级别和文本组成的表。我需要编写一个例程,对缩进级别内的文本进行“自然”排序[这是较低缩进级别的子级]。我在分析例程和连接方面的经验有限,但从我在这里和其他地方读到的内容来看,它们似乎可以用来帮助我的事业,但我不知道如何使用Sql Oracle-多级自然排序行,sql,oracle,plsql,oracle10g,Sql,Oracle,Plsql,Oracle10g,使用Oracle 10.2.0 我有一个由行号、缩进级别和文本组成的表。我需要编写一个例程,对缩进级别内的文本进行“自然”排序[这是较低缩进级别的子级]。我在分析例程和连接方面的经验有限,但从我在这里和其他地方读到的内容来看,它们似乎可以用来帮助我的事业,但我不知道如何使用 CREATE TABLE t (ord NUMBER(5), indent NUMBER(3), text VARCHAR2(254)); INSERT INTO t (ord, indent, text) VALUE
CREATE TABLE t (ord NUMBER(5), indent NUMBER(3), text VARCHAR2(254));
INSERT INTO t (ord, indent, text) VALUES (10, 0, 'A');
INSERT INTO t (ord, indent, text) VALUES (20, 1, 'B');
INSERT INTO t (ord, indent, text) VALUES (30, 1, 'C');
INSERT INTO t (ord, indent, text) VALUES (40, 2, 'D');
INSERT INTO t (ord, indent, text) VALUES (50, 2, 'Z');
INSERT INTO t (ord, indent, text) VALUES (60, 2, 'E');
INSERT INTO t (ord, indent, text) VALUES (70, 1, 'F');
INSERT INTO t (ord, indent, text) VALUES (80, 2, 'H');
INSERT INTO t (ord, indent, text) VALUES (90, 2, 'G');
INSERT INTO t (ord, indent, text) VALUES (100, 3, 'J');
INSERT INTO t (ord, indent, text) VALUES (110, 3, 'H');
这:
…返回:
ORD INDENT TXT
---------- ---------- ----------------------------------------------
10 0 A
20 1 B
30 1 C
40 2 D
50 2 Z
60 2 E
70 1 F
80 2 H
90 2 G
100 3 J
110 3 H
选择11行
在我为您定义的情况下,我需要我的例程设置ORD 60=50和ORD 50=60[翻转它们],因为E在D之后,在Z之前。
与作战需求文件80和90相同[90带来了100和110,因为它们属于作战需求文件]、100和110。最终输出应为:
ORD INDENT TXT
结果是每个缩进级别在其缩进级别和父缩进级别内按字母顺序排序 这是我要做的工作。不知道在更大的电视机上会有多高效。对我来说,最困难的部分是仅基于缩进和原始顺序识别给定行的父级
WITH
a AS (
SELECT
t.*,
( SELECT MAX( ord )
FROM t t2
WHERE t2.ord < t.ord AND t2.indent = t.indent-1
) AS parent_ord
FROM
t
)
SELECT
ROWNUM*10 AS ord,
indent,
rpad( ' ', LEVEL-1, ' ' ) || text
FROM
a
CONNECT BY
PRIOR ord = parent_ord
START WITH
parent_ord IS NULL
ORDER SIBLINGS BY
text
好的,给你。数据结构中的难点在于父节点不明确,因此查询的第一部分除了根据每个节点的规则识别父节点外,什么都不做,它将所有子节点都深一层,一旦识别小于或等于起始节点,就停止 剩下的很简单,基本上只是一些带有connectby的递归,以便按照您希望的顺序对项目进行动态重新编号
WITH OrdWithParentInfo AS
(SELECT ID,
INDENT,
TEXT,
MIN(ParentID) ParentID
FROM (SELECT O.*,
CASE
WHEN (CONNECT_BY_ROOT ID = ID) THEN
NULL
ELSE
CONNECT_BY_ROOT ID
END ParentID
FROM (SELECT ROWNUM ID,
INDENT,
TEXT
FROM T
ORDER BY ORD) O
WHERE (INDENT = CONNECT_BY_ROOT INDENT + 1)
OR (CONNECT_BY_ROOT ID = ID)
CONNECT BY ((ID = PRIOR ID + 1) AND (INDENT > CONNECT_BY_ROOT INDENT)))
GROUP BY ID,
INDENT,
TEXT)
SELECT ROWNUM * 10 ORD, O.INDENT, O.TEXT
FROM OrdWithParentInfo O
START WITH O.ParentID IS NULL
CONNECT BY O.ParentID = PRIOR ID
ORDER SIBLINGS BY O.Text;
对我来说,这听起来像是一个家庭作业。对于家庭作业来说,这似乎很难,但谁知道呢?这不是一个家庭作业。我已经大大简化了表格和数据,将重点放在答案上,而不是无关的数据上。呵呵。。。几乎同时发布。我必须承认,你找到父母的方式要小得多,我很难做到这一点……谢谢!我简直不敢相信找到了父母!奇妙的解决方案!我想是的,尽管我不认为自己是伟大的头脑。无论如何,这很有趣。
WITH
a AS (
SELECT
t.*,
( SELECT MAX( ord )
FROM t t2
WHERE t2.ord < t.ord AND t2.indent = t.indent-1
) AS parent_ord
FROM
t
)
SELECT
ROWNUM*10 AS ord,
indent,
rpad( ' ', LEVEL-1, ' ' ) || text
FROM
a
CONNECT BY
PRIOR ord = parent_ord
START WITH
parent_ord IS NULL
ORDER SIBLINGS BY
text
WITH OrdWithParentInfo AS
(SELECT ID,
INDENT,
TEXT,
MIN(ParentID) ParentID
FROM (SELECT O.*,
CASE
WHEN (CONNECT_BY_ROOT ID = ID) THEN
NULL
ELSE
CONNECT_BY_ROOT ID
END ParentID
FROM (SELECT ROWNUM ID,
INDENT,
TEXT
FROM T
ORDER BY ORD) O
WHERE (INDENT = CONNECT_BY_ROOT INDENT + 1)
OR (CONNECT_BY_ROOT ID = ID)
CONNECT BY ((ID = PRIOR ID + 1) AND (INDENT > CONNECT_BY_ROOT INDENT)))
GROUP BY ID,
INDENT,
TEXT)
SELECT ROWNUM * 10 ORD, O.INDENT, O.TEXT
FROM OrdWithParentInfo O
START WITH O.ParentID IS NULL
CONNECT BY O.ParentID = PRIOR ID
ORDER SIBLINGS BY O.Text;