6

मैं एसक्यूएल सर्वर में निम्न तालिका (2012) हैएसक्यूएल सर्वर CTE और आदेश

MyTable:

Id  __ParentId  Priority 
1  NULL   NULL  
2  1    100  
3  1    300  
4  1    200  
5  4    100  
6  4    200  
7  6    100  
8  5    100  
9  5    200  
10  9    100  
11  5    50  

__ParentId स्तंभ का संदर्भ ईद पता करने के लिए किसी एक पंक्ति के माता-पिता और यह रिकर्सन के कई स्तरों पर जा सकता है (उदाहरण के लिए, आईडी 85 का बच्चा है जो 4 का बच्चा है जोका बच्चा है 0)।

इसके अलावा, प्राथमिकता कॉलम दिखाता है कि बच्चों को माता-पिता के भीतर उपस्थित होना चाहिए (सबसे कम संख्या प्राप्त प्राथमिकता)।

तो, अंतिम तालिका मैं प्राप्त करना चाहते हैं है:

Id  __ParentId Priority Order 
1  NULL  NULL  1  
2  1   100   2  
4  1   200   3  
5  4   100   4  
11  5   50   5  
8  5   100   6  
9  5   200   7  
10  9   100   8  
6  4   200   9  
7  6   100   10  
3  1   300   11  

एक स्पर्श व्याख्या करने के लिए, हम उस 21 का एक बच्चा है और सर्वोच्च प्राथमिकता है है, लेकिन कोई संतान नहीं है, तो हम वहां रुकते हैं, फिर 4 अगली प्राथमिकता बच्चा है, इसलिए यह आगे जाता है, लेकिन फिर हम प्राथमिकता और पदानुक्रम के आधार पर अपने बच्चों और उनके बच्चों में अलग हो जाते हैं।

या, एक वृक्ष संरचना के माध्यम से समझाने के लिए:

1 
    2 
    4 
     5 
      11 
      8 
      9 
       10 
     6 
      7 
    3 

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

उत्तर

8

SQL2008 +:

समाधान निम्नलिखित का प्रयास करें:

DECLARE @TableA TABLE (
    Id   INT NOT NULL PRIMARY KEY, 
    __ParentId INT NULL, 
    [Priority] INT NULL 
); 

INSERT @TableA (Id, __ParentId, [Priority]) 
VALUES 
(1 ,NULL,NULL), 
(2 ,1 ,100), 
(3 ,1 ,300), 
(4 ,1 ,200), 
(5 ,4 ,100), 
(6 ,4 ,200), 
(7 ,6 ,100), 
(8 ,5 ,100), 
(9 ,5 ,200), 
(10,9 ,100), 
(11,5 ,50 ); 

WITH CteRecursive 
AS (
    SELECT a.Id, a.__ParentId, a.[Priority], CONVERT(HIERARCHYID, '/' + LTRIM(a.Id) + '/') AS HID 
    FROM @TableA a 
    WHERE a.__ParentId IS NULL 
    UNION ALL 
    SELECT cld.Id, cld.__ParentId, cld.[Priority], CONVERT(HIERARCHYID, prt.HID.ToString() + LTRIM(cld.[Priority]) + '/') AS HID 
    FROM  CteRecursive prt -- Parent 
    JOIN @TableA cld ON prt.Id = cld.__ParentId -- Child 
    WHERE cld.__ParentId IS NOT NULL 
) 
SELECT *, r.HID.ToString() AS HIDToString FROM CteRecursive r 
ORDER BY r.HID ASC 

परिणाम:

enter image description here

Demo

नोट # 1: यह समाधान HIERARCHYID आदेश में से एक संपत्ति का उपयोग करता है: HID मूल्यों गहराई पहले दृष्टिकोण का उपयोग कर आदेश दिया जाता है (इसका मतलब है माता पिता और तो सभी बच्चे)।

को देखते हुए दो hierarchyid मूल्यों ए और बी, बी तुलना में एक कम एक पेड़ की एक गहराई-प्रथम ट्रेवर्सल में ख से पहले आता है मतलब है। पदानुक्रमित डेटा प्रकारों पर सूचकांक गहराई से पहले क्रम में हैं, और गहराई-पहले ट्रैवर्सल में एक दूसरे के नजदीक नोड्स एक दूसरे के पास संग्रहीत हैं। उदाहरण के लिए, रिकॉर्ड के बच्चे उस रिकॉर्ड के समीप संग्रहीत होते हैं। अधिक जानकारी के लिए, पदानुक्रमित डेटा (SQL सर्वर) देखें।

Reference

+0

नाइस - कभी नहीं माना जाता कि मैं एक पदानुक्रम आईडी +1 –

+0

में दूसरा तत्व जोड़ सकता हूं यह समाधान भी खूबसूरत है !!! - ** आपको बहुत धन्यवाद ** - मैंने कभी नहीं सोचा/वास्तविक टेक्स्ट कॉन्सटेनेशन करना जानता था जो ** BRILLIANT ** है। यह ठीक उसी तरह काम करता है, एकमात्र कारण मैं समाधान के रूप में आपका निशान नहीं लगा सकता क्योंकि मुझे एक चुनना है और जॉन ने तेज़ी से जवाब दिया है ... मैं वास्तव में आपको धन्यवाद नहीं दे सकता, हालांकि !!! –

+0

@ जॉन बुस्टोस उस उत्तर को स्वीकार करें जो आपके लिए सबसे अच्छा काम करता है। –

6

यह एक मानक रिकर्सिव सीटी है, लेकिन थोड़ा मोड़ के साथ। हम SEQUENCE जोड़ते हैं जो प्राथमिकता (इस मामले में) द्वारा row_numbers आदेश की एक कंपाउंड स्ट्रिंग है।

उदाहरण

Declare @YourTable Table ([Id] varchar(50),[__ParentId] varchar(50),[Priority] varchar(50)) 
Insert Into @YourTable Values 
(1,NULL,NULL) 
,(2,1,100) 
,(3,1,300) 
,(4,1,200) 
,(5,4,100) 
,(6,4,200) 
,(7,6,100) 
,(8,5,100) 
,(9,5,200) 
,(10,9,100) 
,(11,5,50) 

Declare @Top int   = null  --<< Sets top of Hier Try 4 
Declare @Nest varchar(25) = '|-----' --<< Optional: Added for readability 

;with cteP as (
     Select Seq = cast(10000+Row_Number() over (Order by [Priority]) as varchar(500)) 
      ,ID 
      ,__ParentId 
      ,Lvl=1 
      ,Priority 
     From @YourTable 
     Where IsNull(@Top,-1) = case when @Top is null then isnull(__ParentId ,-1) else ID end 
     Union All 
     Select Seq = cast(concat(p.Seq,'.',10000+Row_Number() over (Order by r.[Priority])) as varchar(500)) 
      ,r.ID 
      ,r.__ParentId 
      ,p.Lvl+1 
      ,r.Priority 
     From @YourTable r 
     Join cteP p on r.__ParentId = p.ID) 
Select A.ID 
     ,A.__ParentId 
     ,A.Lvl 
     ,A.Priority 
     ,Name = Replicate(@Nest,A.Lvl-1) +cast(ID as varchar(25)) 
From cteP A 
Order By Seq 

रिटर्न

enter image description here

+1

बस - वाह !!!! - इसे अभी आज़माने के लिए जा रहे हैं, लेकिन ** आपको धन्यवाद !!! ** –

+1

मुझे यह पूरी तरह से काम कर रहा है .... वास्तव में आप को धन्यवाद नहीं दे सकता !!!!! –

+0

@ जॉनबस्टोस हैप्पी ने –

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