2013-04-28 5 views
6

मैं एक परिसंपत्ति डेटाबेस एक पदानुक्रम है पर काम कर रहा हूँ की क्वेरी। इसके अलावा, एक "संदर्भ एसेट" तालिका है, जो प्रभावी रूप से किसी संपत्ति को इंगित करती है। संदर्भ संपत्ति मूल रूप से ओवरराइड के रूप में कार्य करती है, लेकिन यह चुना जाता है जैसे कि यह एक अद्वितीय, नई संपत्ति थी। सेट होने वाले ओवरराइड में से एक है, parent_id है।एसक्यूएल सर्वर: श्रेणीबद्ध और संदर्भित डाटा

कॉलम कि पदानुक्रम का चयन के लिए प्रासंगिक हैं:
एसेट: आईडी (प्राथमिक), PARENT_ID
एसेट संदर्भ: आईडी (प्राथमिक), ASSET_ID (foreignkey-> एसेट), PARENT_ID (हमेशा एक परिसंपत्ति)
- --EDITED 5/27 ----

नमूना प्रासंगिक तालिका डेटा (के बाद मिलती है):

id | asset_id | name   | parent_id | milestone | type 

    3  3  suit    null  march  shape 
    4  4  suit_banker   3   april  texture 
    5  5  tie    null  march  shape 
    6  6  tie_red    5   march  texture 
    7  7  tie_diamond   5   june  texture 
    -5  6  tie_red    4   march  texture 

आईडी < 0 (अंतिम पंक्ति की तरह) संदर्भित संपत्तियों को इंगित करें। संदर्भित संपत्तियों में कुछ कॉलम हैं जिन्हें ओवरराइड किया गया है (इस मामले में, केवल parent_id महत्वपूर्ण है)।

उम्मीद है कि अगर मैं अप्रैल से सभी परिसंपत्तियों का चयन करें, मैं मिलते जुलते क्वैरी के पूरे पेड़ की शाखाओं को पाने के लिए एक उच्च माध्यमिक का चयन करना चाहिए है: तो शुरू में क्वेरी मिलान परिणाम होगा

में:

4  4  suit_banker   3   april  texture 

फिर CTE के बाद, हम पूरा पदानुक्रम हो और हमारे परिणाम यह (अब तक इस काम कर रहा है)

0 होना चाहिए
3  3  suit    null  march  shape 
    4  4  suit_banker   3   april  texture 
    -5  6  tie_red    4   march  texture 

और आप देखते हैं, आईडी की मूल: -5 वहाँ है, लेकिन क्या याद आ रही है, कि जरूरत है, संदर्भित संपत्ति है, और संदर्भित संपत्ति की मूल:

5  5  tie    null  march  shape 
    6  6  tie_red    5   march  texture 

वर्तमान में मेरे समाधान इस के लिए काम करता है, लेकिन यह केवल संदर्भ की एक भी गहराई तक ही सीमित है (और मुझे लगता है कि कार्यान्वयन काफी बदसूरत है)।

--- संपादित ---- यहाँ मेरी प्राथमिक चुनाव समारोह है। यह बेहतर प्रदर्शन करना चाहिए कि वास्तविक जटिलता कहां है: संपत्ति संदर्भ।

Select A.id as id, A.id as asset_id, A.name,A.parent_id as parent_id, A.subPath, T.name as typeName, A2.name as parent_name, B.name as batchName, 
L.name as locationName,AO.owner_name as ownerName, T.id as typeID, 
M.name as milestoneName, A.deleted as bDeleted, 0 as reference, W.phase_name, W.status_name 
FROM Asset as A Inner Join Type as T on A.type_id = T.id 
Inner Join Batch as B on A.batch_id = B.id 
Left Join Location L on A.location_id = L.id 
Left Join Asset A2 on A.parent_id = A2.id 
Left Join AssetOwner AO on A.owner_id = AO.owner_id 
Left Join Milestone M on A.milestone_id = M.milestone_id 
Left Join Workflow as W on W.asset_id = A.id 
where A.deleted <= @showDeleted 

UNION 

Select -1*AR.id as id, AR.asset_id as asset_id, A.name, AR.parent_id as parent_id, A.subPath, T.name as typeName, A2.name as parent_name, B.name as batchName, 
L.name as locationName,AO.owner_name as ownerName, T.id as typeID, 
M.name as milestoneName, A.deleted as bDeleted, 1 as reference, NULL as phase_name, NULL as status_name 
FROM Asset as A Inner Join Type as T on A.type_id = T.id 
Inner Join Batch as B on A.batch_id = B.id 
Left Join Location L on A.location_id = L.id 
Left Join Asset A2 on AR.parent_id = A2.id 
Left Join AssetOwner AO on A.owner_id = AO.owner_id 
Left Join Milestone M on A.milestone_id = M.milestone_id 
Inner Join AssetReference AR on AR.asset_id = A.id 
where A.deleted <= @showDeleted 

मेरे पास एक संग्रहीत प्रक्रिया है जो एक temp तालिका (#temp) लेती है और पदानुक्रम के सभी तत्व पाती है।रणनीति मैं कार्यरत था इस:

  1. # से
  2. क्वेरी से मेल खाता संपत्ति के पूरे पदानुक्रम जाओ एक अस्थायी तालिका में पूरे सिस्टम पदानुक्रम (#treeIDs) प्रत्येक पूरे पेड़ की टहनी की अल्पविराम द्वारा अलग सूची के प्रतिनिधित्व का चयन करें (अस्थायी)
  3. जाओ सभी संदर्भ संपत्ति पदानुक्रम
  4. से आस्तियों द्वारा की ओर इशारा किया सभी संदर्भ संपत्ति

यह अब के लिए काम करता है के पदानुक्रम पार्स संदर्भ संपत्ति हमेशा से रहे हैं क्योंकि ला एक शाखा पर सेंट आइटम, लेकिन अगर वे नहीं थे, तो मुझे लगता है कि मैं परेशानी में होगा। मुझे लगता है कि मुझे रिकर्सन के कुछ बेहतर रूप की आवश्यकता है।

यहाँ मेरे वर्तमान कोड है, जो काम कर रहा है, लेकिन मैं इसे पर गर्व नहीं कर रहा हूँ, और मुझे पता है कि यह मजबूत नहीं है (क्योंकि यह तभी काम करता है के संदर्भ तल पर हैं):

चरण 1। संपूर्ण पदानुक्रम

;WITH Recursive_CTE AS (
SELECT Cast(id as varchar(100)) as Hierarchy, parent_id, id 
FROM #assetIDs 
Where parent_id is Null 

UNION ALL 

SELECT 
CAST(parent.Hierarchy + ',' + CAST(t.id as varchar(100)) as varchar(100)) as Hierarchy, t.parent_id, t.id 
FROM Recursive_CTE parent 
INNER JOIN #assetIDs t ON t.parent_id = parent.id 
) 



Select Distinct h.id, Hierarchy as idList into #treeIDs 
FROM (Select Hierarchy, id FROM Recursive_CTE) parent 
CROSS APPLY dbo.SplitIDs(Hierarchy) as h 

चरण 2. निर्माण सभी परिसंपत्तियों क्वेरी से मेल खाने

Select DISTINCT L.id into #RelativeIDs FROM #treeIDs 
CROSS APPLY dbo.SplitIDs(idList) as L 
WHERE #treeIDs.id in (Select id FROM #temp) 

चरण 3. की ​​शाखाओं का चयन करें जाओ सभी संदर्भ आस्तियों शाखाओंमें 63,210 (संदर्भ संपत्ति, नकारात्मक आईडी मान हैं इसलिए आईडी < 0 हिस्सा)

Select asset_id INTO #REFLinks FROM #AllAssets WHERE id in 
(Select #AllAssets.asset_id FROM #AllAssets Inner Join #RelativeIDs 
on #AllAssets.id = #RelativeIDs.id Where #RelativeIDs.id < 0) 

चरण 4. कुछ भी की शाखाओं हो जाओ कदम 3

Select DISTINCT L.id into #extraRelativeIDs FROM #treeIDs 
CROSS APPLY dbo.SplitIDs(idList) as L 
WHERE 
exists (Select #REFLinks.asset_id FROM #REFLinks WHERE #REFLinks.asset_id = #treeIDs.id) 
and Not Exists (select id FROM #RelativeIDs Where id = #treeIDs.id) 

मैं सिर्फ दिखाने के लिए कोशिश की है में पाया प्रासंगिक कोड मैं किसी भी व्यक्ति के लिए बहुत आभारी हूं जो मुझे बेहतर समाधान खोजने में मदद कर सकता है!

+0

आप किस एसक्यूएल संस्करण का उपयोग कर रहे हैं? http://msdn.microsoft.com/de-de/library/bb677290.aspx – NickD

+0

एसक्यूएल सर्वर 2012, लेकिन हमने अभी इसे स्विच किया है, इसलिए इनमें से अधिकांश 2008 – haggercody

उत्तर

1
--getting all of the children of a root node (could be > 1) and it would require revising the query a bit 

DECLARE @AssetID int = (select AssetId from Asset where AssetID is null); 


--algorithm is relational recursion 
--gets the top level in hierarchy we want. The hierarchy column 
--will show the row's place in the hierarchy from this query only 
--not in the overall reality of the row's place in the table 

WITH Hierarchy(Asset_ID, AssetID, Levelcode, Asset_hierarchy) 
AS 
(
SELECT AssetID, Asset_ID, 
     1 as levelcode, CAST(Assetid as varchar(max)) as Asset_hierarchy 
FROM Asset 
WHERE [email protected] 

UNION ALL 

--joins back to the CTE to recursively retrieve the rows 
--note that treelevel is incremented on each iteration 

SELECT A.Parent_ID, B.AssetID, 
     Levelcode + 1 as LevelCode, 
     A.assetID + '\' + cast(A.Asset_id as varchar(20)) as Asset_Hierarchy 
FROM Asset AS a 
      INNER JOIN dbo.Batch AS Hierarchy 
      --use to get children, since the parentId of the child will be set the value 
      --of the current row 
      on a.assetId= b.assetID 
--use to get parents, since the parent of the Asset_Hierarchy row will be the asset, 
      --not the parent. 
      on Asset.AssetId= Asset_Hierarchy.parentID 


SELECT a.Assetid,a.name, 
     Asset_Hierarchy.LevelCode, Asset_Hierarchy.hierarchy 
FROM  Asset AS a 
     INNER JOIN Asset_Hierarchy 
       ON A.AssetID= Asset_Hierarchy.AssetID 
ORDER BY Hierarchy ; 
--return results from the CTE, joining to the Asset data to get the asset name 
---that is the structure you will want. I would need a little more clarification of your table structure 
+0

वाह। प्रतिभाशाली। धन्यवाद! – haggercody

0

यह आपकी अंतर्निहित तालिका संरचना को जानने में मदद करेगा। दो दृष्टिकोण हैं जो आपके पर्यावरण के आधार पर काम करना चाहिए: एसक्यूएल एक्सएमएल को समझता है ताकि आप अपने एसक्यूएल को एक्सएमएल संरचना के रूप में प्राप्त कर सकें या बस एक पंक्ति हो जिसमें प्रत्येक पंक्ति वस्तु के साथ एक अद्वितीय प्राथमिक कुंजी आईडी और अभिभावक हो। आईडी माता-पिता के लिए एफके है। नोड के लिए डेटा केवल मानक कॉलम हैं। आप प्रत्येक नोड के लिए घोंसले की डिग्री निर्धारित करने के लिए गणना किए गए कॉलम को सशक्त करने वाले सीटी या फ़ंक्शन का उपयोग कर सकते हैं। सीमा यह है कि एक नोड में केवल एक माता पिता हो सकता है।

+0

के लिए लिखा गया था, इसे देखने के लिए धन्यवाद।
मैंने ओपी को चयन फ़ंक्शन के साथ अपडेट किया है, जो तालिका संरचना को बेहतर दिखाता है। मुद्दा वास्तव में AssetReference तालिका के आसपास है। मुझे एक विशेष स्थिति के बारे में बताएं: पर विचार करें मैं बैच टोपी द्वारा संपत्ति का चयन करें: मैं [BallCap] मिल - तो मैं [BallCap] के लिए (ठीक अब तक) पूरे पेड़ की टहनी चयन लेकिन तब मैं में एक AssetReference मुठभेड़ पेड़ अब मुझे मूल संपत्ति संदर्भित करना है और फिर मुझे इस संपत्ति – haggercody

+0

के लिए पूरे पेड़ की आवश्यकता है क्या आप कह रहे हैं कि आपके पास नोड के लिए शाखाओं का एक सेट है और उन शाखाओं में से एक पर नोड हो सकता है एक पूरी तरह से अलग पेड़? –

+0

हां, एक शाखा में एक नोड एक और नोड 'संदर्भ' कर सकता है जो एक अलग पेड़ शाखा में हो सकता है। यह 'संदर्भ' एक अलग तालिका (AssetReference) से है। क्या मैंने यहां एक डिजाइन आदेश तोड़ दिया? – haggercody

संबंधित मुद्दे