أوراكل - الصفوف نوع الطبيعية على مستويات متعددة

StackOverflow https://stackoverflow.com/questions/1633454

  •  06-07-2019
  •  | 
  •  

سؤال

<ع> استخدام أوراكل 10.2.0.

ولدي الجدول الذي يتكون من رقم السطر، وهو مستوى المسافة البادئة، والنص. ولست بحاجة لكتابة روتين إلى 'الطبيعية' فرز النص ضمن مستوى المسافة البادئة [أي طفل من مستوى المسافة البادئة أقل]. لدي خبرة محدودة مع إجراءات التحليل والاتصال عن طريق / قبل، ولكن من ما قرأت هنا وفي أماكن أخرى، يبدو أنها يمكن أن تكون وضعت لاستخدامها للمساعدة في قضيتي، ولكنني لا يمكن معرفة كيفية القيام بذلك.

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');  

وهذا ما يلي:

SELECT ord, indent, LPAD(' ', indent, ' ') || text txt FROM t;  

... العوائد:

   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.
الشيء نفسه مع ORD 80 و 90 [مع 90 ليصل 100 و 110 مع ذلك لأنهم ينتمون إليها] و 100 و 110. وينبغي أن يكون الناتج النهائي:

   ORD     INDENT TXT  

    10          0 A  
    20          1  B  
    30          1  C  
    40          2   D  
    50          2   E  
    60          2   Z  
    70          1  F  
    80          2   G  
    90          3    H  
   100          3    J 
   110          2   H  

والنتيجة هي أن كل مستوى المسافة البادئة يتم فرز أبجديا، ضمن مستوى المسافة البادئة، في حدود مستوى المسافة البادئة الأم.

هل كانت مفيدة؟

المحلول

وهنا ما حصلت على العمل. أي فكرة عن كيفية كفاءة قد يكون على مجموعات أكبر. الجزء الصعب بالنسبة لي هو تحديد "الأم" لصف معين يعتمد فقط على النظام البادئة والأصلي.

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

نصائح أخرى

حسنا، هنا تذهب. الجزء الصعب في بنية البيانات الخاصة بك هو أن الأم ليست (صراحة) المعروف، حتى أن الجزء الأول من الاستعلام لا يفعل شيئا ولكن التعرف على الأم وفقا للقواعد (لكل عقدة، فإنه يحصل على كل subnodes مستوى واحد عميق، ووقف بمجرد identation أصغر أو يساوي عقدة البداية).

وبقية من السهل، في الأساس سوى بعض العودية مع الاتصال عن طريق للحصول على العناصر بالترتيب الذي تريده (إعادة ترقيم لهم حيوي).

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;
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top