متعددة شجرة الوالدين (أو الدوغراف حرفان يمثلا ن صوتا مفردا) مزود خدمة تنفيذ 2005
-
21-08-2019 - |
سؤال
ولست بحاجة لتنفيذ شجرة متعددة أصليا (أو الدوغراف حرفان يمثلا ن صوتا مفردا) على 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 ).
وأي مساعدة؟ ما هو رأيكم أيها الأصدقاء؟ شكرا جزيلا لك على وقتك =)
وهتاف!
المحلول
حسنا، لقد جئت أخيرا مع الحل التالي. انها الطريقة لقد وجدت لدعم أشجار متعددة الجذور و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