متعددة شجرة الوالدين (أو الدوغراف حرفان يمثلا ن صوتا مفردا) مزود خدمة تنفيذ 2005

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

سؤال

ولست بحاجة لتنفيذ شجرة متعددة أصليا (أو الدوغراف حرفان يمثلا ن صوتا مفردا) على SQL خادم عام 2005. لقد قرأت عدة مقالات، ولكن معظمها يستخدم الأشجار وحيدة أصليا مع جذر فريدة من نوعها مثل واحدة بعد.

-My PC
   -Drive C
      -Documents and Settings
      -Program Files
         -Adobe
         -Microsoft
      -Folder X
   -Drive D
      -Folder Y
      -Folder Z

في هذا واحد، كل شيء مستمد من عنصر الجذر (PC الكمبيوتر).

في حالتي، يمكن للطفل أن يكون أكثر من 1 الأم، كما يلي:

G  A
 \ /
  B
 / \ 
X   C
  /  \
  D   E
  \ /
   F

وهكذا لدي البرمجية التالية:

create table #ObjectRelations
(
    Id varchar(20),
    NextId varchar(20)
)

insert into #ObjectRelations values ('G', 'B')
insert into #ObjectRelations values ('A', 'B') 
insert into #ObjectRelations values ('B', 'C')
insert into #ObjectRelations values ('B', 'X')
insert into #ObjectRelations values ('C', 'E') 
insert into #ObjectRelations values ('C', 'D') 
insert into #ObjectRelations values ('E', 'F') 
insert into #ObjectRelations values ('D', 'F') 

declare @id varchar(20)
set @id = 'A';

WITH Objects (Id, NextId) AS
( -- This is the 'Anchor' or starting point of the recursive query
  SELECT rel.Id,
         rel.NextId
    FROM #ObjectRelations rel
   WHERE rel.Id = @id
   UNION ALL -- This is the recursive portion of the query
  SELECT rel.Id,
         rel.NextId
    FROM #ObjectRelations rel
   INNER JOIN Objects -- Note the reference to CTE table name (Recursive Join)
      ON rel.Id = Objects.NextId
)
SELECT  o.*
FROM    Objects o

drop table #ObjectRelations

والتي ترجع SET التالية:

Id                   NextId
-------------------- --------------------
A                    B
B                    C
B                    X
C                    E
C                    D
D                    F
E                    F

والنتيجة المتوقعة SET:

Id                   NextId
-------------------- --------------------
G                    B
A                    B
B                    C
B                    X
C                    E
C                    D
D                    F
E                    F

لاحظ أن العلاقة G-> B مفقود، لأنه يسأل عن كائن البداية (الذي لا يعمل بالنسبة لي أيضا، لأنني لا أعرف الكائن الجذر من البداية) واستخدام كبداية ونقطة تجاهل G-> العلاقة B.

وهكذا، هذا الرمز لا يعمل في حالتي لأنه يسأل عن كائن البدء، الذي هو واضح في شجرة وحيدة الوالد (سوف يكون دائما هو الكائن الجذر). ولكن في شجرة متعددة الأم، هل يمكن أن يكون أكثر من 1 "جذور" وجوه (كما هو الحال في المثال، G و A هي الأشياء "الجذر"، حيث الجذر هو كائن التي لم يقم أحد الوالدين (سلف)).

وهكذا انا من النوع stucked هنا ... ولست بحاجة لتعديل الاستعلام للا تسأل لكائن البداية وبشكل متكرر اجتياز الشجرة بأكملها. أنا لا أعرف إذا كان ذلك ممكنا مع (رقم، NextId) تنفيذ ... قد تكون ولست بحاجة لتخزينه مثل رسم بياني باستخدام نوع من الإصابة مصفوفة، مصفوفة التجاور أو أيا كان (انظر <لأ href = "HTTP: / /willets.org/sqlgraphs.html "يختلط =" نوفولو noreferrer "> http://willets.org/sqlgraphs.html ).

وأي مساعدة؟ ما هو رأيكم أيها الأصدقاء؟ شكرا جزيلا لك على وقتك =)

وهتاف!

المصدر: المصدر 1 المصدر 2 المصدر 3

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

المحلول

حسنا، لقد جئت أخيرا مع الحل التالي. انها الطريقة لقد وجدت لدعم أشجار متعددة الجذور وdigraphs ركوب الدراجات أيضا.

create table #ObjectRelations
(
    Id varchar(20),
    NextId varchar(20)
)

/* Cycle */
/*
insert into #ObjectRelations values ('A', 'B')
insert into #ObjectRelations values ('B', 'C') 
insert into #ObjectRelations values ('C', 'A')
*/

/* Multi root */

insert into #ObjectRelations values ('G', 'B')
insert into #ObjectRelations values ('A', 'B') 
insert into #ObjectRelations values ('B', 'C')
insert into #ObjectRelations values ('B', 'X')
insert into #ObjectRelations values ('C', 'E') 
insert into #ObjectRelations values ('C', 'D') 
insert into #ObjectRelations values ('E', 'F') 
insert into #ObjectRelations values ('D', 'F') 


declare @startIds table
(
    Id varchar(20) primary key
)

;WITH 
    Ids (Id) AS
    (
        SELECT  Id
        FROM    #ObjectRelations
    ),
    NextIds (Id) AS
    (
        SELECT  NextId
        FROM    #ObjectRelations
    )
INSERT INTO @startIds
/* This select will not return anything since there are not objects without predecessor, because it's a cyclic of course */
SELECT DISTINCT
    Ids.Id
FROM
    Ids
LEFT JOIN
    NextIds on Ids.Id = NextIds.Id
WHERE
    NextIds.Id IS NULL
UNION
/* So let's just pick anyone. (the way I will be getting the starting object for a cyclic doesn't matter for the regarding problem)*/
SELECT TOP 1 Id FROM Ids

;WITH Objects (Id, NextId, [Level], Way) AS
( -- This is the 'Anchor' or starting point of the recursive query
  SELECT rel.Id,
         rel.NextId,
         1,
         CAST(rel.Id as VARCHAR(MAX))
    FROM #ObjectRelations rel
   WHERE rel.Id IN (SELECT Id FROM @startIds)

   UNION ALL -- This is the recursive portion of the query

  SELECT rel.Id,
         rel.NextId,
         [Level] + 1,
         RecObjects.Way + ', ' + rel.Id
    FROM #ObjectRelations rel
   INNER JOIN Objects RecObjects -- Note the reference to CTE table name (Recursive Join)
      ON rel.Id = RecObjects.NextId
   WHERE RecObjects.Way NOT LIKE '%' + rel.Id + '%'

)
SELECT  DISTINCT 
        Id,
        NextId,
        [Level]
FROM    Objects
ORDER BY [Level]

drop table #ObjectRelations

ويمكن أن تكون مفيدة لشخص ما. هو الحال بالنسبة لي = P بفضل

نصائح أخرى

إذا كنت ترغب في استخدام كافة الكائنات الجذر ككائنات البدء، يجب عليك أولا تحديث البيانات الخاصة بك لتضمين معلومات حول الكائنات الجذر (ويترك). يجب أن تضيف إدراج التالية:

insert into #ObjectRelations values (NULL, 'G')
insert into #ObjectRelations values (NULL, 'A')
insert into #ObjectRelations values ('X', NULL)
insert into #ObjectRelations values ('F', NULL)

وبالطبع يمكن أيضا كتابة الاستعلام الثابت في مثل هذه الطريقة التي تحددها كجذر الليمفاوية السجلات التي لها Id أن لا يحدث كما NextId، ولكن هذا هو أسهل.

وبعد ذلك، تعديل الاستعلام مرساة لتبدو مثل هذا:

SELECT rel.Id,
       rel.NextId
FROM #ObjectRelations rel
WHERE rel.Id IS NULL

إذا قمت بتشغيل هذا الاستعلام، سترى أن تحصل على الكثير من التكرارات، والكثير من الأقواس تحدث عدة مرات. وذلك لأن لديك الآن نتيجتين من الاستعلام الخاص مرساة وبالتالي اجتاز شجرة مرتين.

وهذا يمكن أن تكون ثابتة عن طريق تغيير حدد بيان لهذه (لاحظ DISTINCT):

SELECT DISTINCT o.*
FROM   Objects o

إذا كنت لا تريد أن تفعل إدراج اقترحه رونالد، هذا لن يفعل!

WITH CTE_MultiParent  (ID, ParentID) 
AS 
(
    SELECT ID, ParentID FROM #ObjectRelations
    WHERE ID NOT IN 
    (
        SELECT DISTINCT ParentID FROM #ObjectRelations
    )
    UNION ALL
    SELECT ObjR.ID, ObjR.ParentID FROM #ObjectRelations ObjR INNER JOIN CTE_MultiParent
    ON CTE_MultiParent.ParentID = ObjR.Id
)

SELECT DISTINCT * FROM CTE_MultiParent
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top