2011-12-19 4 views
7

t-sqlhierarchy आईडी का उपयोग करके मैं उन सभी पंक्तियों को कैसे प्राप्त करूं जिनमें कोई बच्चा नहीं है (जो अंतिम निर्णयकर्ता है)?एसक्यूएल पदानुक्रम Id अंतिम वंशज कैसे प्राप्त करूं?

कहना मेरी मेज इस तरह संरचित है:

Id, 
Name, 
HierarchyId 

और ये पंक्तियां हैं:

1, Craig,/
2, Steve, /1/ 
3, John, /1/1/ 

4, Sam, /2/ 
5, Matt, /2/1/ 
6, Chris, /2/1/1/ 

क्या क्वेरी मुझे जॉन और क्रिस देना होगा?

उत्तर

9

शायद बेहतर तरीके हैं लेकिन नौकरी करने के लिए यह सीम हैं।

declare @T table 
(
    ID int, 
    Name varchar(10), 
    HID HierarchyID 
) 

insert into @T values 
(1, 'Craig', '/'), 
(2, 'Steve', '/1/'), 
(3, 'John', '/1/1/'), 
(4, 'Sam', '/2/'), 
(5, 'Matt', '/2/1/'), 
(6, 'Chris', '/2/1/1/') 

select * 
from @T 
where HID.GetDescendant(null, null) not in (select HID 
              from @T) 

परिणाम:

ID   Name  HID 
----------- ---------- --------------------- 
3   John  0x5AC0 
6   Chris  0x6AD6 

अद्यतन करता है, तो नोड संख्या एक अटूट अनुक्रम में नहीं है 2012-05-22

ऊपर क्वेरी असफल हो जायेगी। यहां एक और संस्करण है जिसका ध्यान रखना चाहिए।

declare @T table 
(
    ID int, 
    Name varchar(10), 
    HID HierarchyID 
) 

insert into @T values 
(1, 'Craig', '/'), 
(2, 'Steve', '/1/'), 
(3, 'John', '/1/1/'), 
(4, 'Sam', '/2/'), 
(5, 'Matt', '/2/1/'), 
(6, 'Chris', '/2/1/2/') -- HID for this row is changed compared to above query 

select * 
from @T 
where HID not in (select HID.GetAncestor(1) 
        from @T 
        where HID.GetAncestor(1) is not null) 
1

जब से तुम केवल लीफ़्स है और आपको उन्हें एक विशिष्ट पूर्वज से प्राप्त करने की आवश्यकता नहीं है, इस तरह एक साधारण गैर पुनरावर्ती पूछताछ काम करना चाहिए:

SELECT * FROM YOUR_TABLE PARENT 
WHERE 
    NOT EXISTS (
     SELECT * FROM YOUR_TABLE CHILD 
     WHERE CHILD.HierarchyId = PARENT.Id 
    ) 

सादे अंग्रेजी में: हर पंक्ति का चयन करें एक बच्चे की पंक्ति के बिना।

यह मानता है कि HierarchyIdId की ओर एक विदेशी कुंजी है, न कि आपके उदाहरण में प्रस्तुत किए गए पूरे "पथ"। यदि ऐसा नहीं है, तो शायद यह पहली बात है जिसे आपको अपने डेटाबेस मॉडल में ठीक करना चाहिए।

SELECT * FROM YOUR_TABLE PARENT 
WHERE 
    NOT EXISTS (
     SELECT * FROM YOUR_TABLE CHILD 
     WHERE 
      CHILD.Id <> PARENT.Id 
      AND CHILD.HierarchyId.IsDescendantOf(PARENT.HierarchyId) = 1 
    ) 

ध्यान दें कि IsDescendantOf किसी भी पंक्ति के ही वंशज मानता है:

--- संपादित करें ---

ठीक है, यहाँ एमएस एसक्यूएल सर्वर-विशिष्ट क्वेरी है कि वास्तव में काम करता है , इसलिए हमें इस स्थिति में CHILD.Id <> PARENT.Id की भी आवश्यकता है।

+0

मैं काफी हद तक निश्चित ओपी एसक्यूएल सर्वर 2008 है, जो असामान्य प्रतिनिधित्व बताते हैं की 'HierarchyID' डेटा प्रकार का उपयोग कर रहा है (http://msdn.microsoft.com/en-us/magazine/cc794278 देखना .aspx)। –

+0

@DanielPratt Ahh ... अब मुझे लगता है कि प्रश्न [एसक्यूएल-सर्वर] के रूप में फिर से टैग किया गया था। –

+0

ब्रैंको का जवाब देने के लिए धन्यवाद, लेकिन मेरे उदाहरण में आईडी फ़ील्ड एक पूर्णांक है और HierarchyId एक वर्ग hierarchyId है, इसलिए उनकी तुलना नहीं की जा सकती है। क्या आप कह रहे हैं कि मुझे पदानुक्रम के लिए तालिका की कुंजी बदलने की जरूरत है? – Eric

1

हाय मैं इसका उपयोग करता हूं और मेरे लिए पूरी तरह से काम करता हूं।

CREATE TABLE [dbo].[Test]([Id] [hierarchyid] NOT NULL, [Name] [nvarchar](50) NULL) 
DECLARE @Parent AS HierarchyID = CAST('/2/1/' AS HierarchyID) -- Get Current Parent 
DECLARE @Last AS HierarchyID 
SELECT @Last = MAX(Id) FROM Test WHERE Id.GetAncestor(1) = @Parent -- Find Last Id for this Parent 

INSERT INTO Test(Id,Name) VALUES(@Parent.GetDescendant(@Last, NULL),'Sydney') -- Insert after Last Id