मैं एसक्यूएल का उपयोग कर मूल्यों का चयन करते समय एक्सएमएल नोड्स की अनुक्रमणिका प्राप्त करने का प्रयास कर रहा हूं:

यह कोड है:

declare @myxml xml ='
<Departments>
    <Department>
        <Employee>
            A
        </Employee>
        <Employee>
            B
        </Employee>
    </Department>

    <Department>
        <Employee>
            C
        </Employee>
        <Employee>
            D
        </Employee>
    </Department>
</Departments>'

Select Emp = m.value('.','varchar(30)') 

from @myxml.nodes('Departments/Department/Employee') X(m)

उपरोक्त क्वेरी का आउटपुट:

Emp 
A
B
C
D

अपेक्षित आउटपुट:

Emp  Department_Index

A         1
B         1
C         2
D         2

यानी मुझे विभाग के तहत हर कर्मचारी के अनुरूप विभाग का सूचकांक चाहिए। यहां कर्मचारी ए और बी विभागों के पहले विभाग से संबंधित हैं और कर्मचारी सी और डी विभागों के दूसरे विभाग से संबंधित हैं।

तो मैं चाहता हूं कि यह जटिल एक्सएमएल बच्चों को माता-पिता के साथ शामिल करे जहां कोई अनूठी कुंजी मौजूद नहीं है।

5
user7739833 5 जुलाई 2018, 11:45

1 उत्तर

सबसे बढ़िया उत्तर

यह एक समाधान है, जहां मैं दावा करता हूं कि यह सभी परिदृश्यों में काम करेगा - हालांकि यह गारंटी नहीं है कि <Department> के माध्यम से ROW_NUMBER() नोड से जुड़ी संख्या प्रत्येक और किसी भी स्थिति में अपनी वास्तविक स्थिति को दर्शाएगी। (टिप्पणियां और लिंक नीचे देखें):

declare @myxml xml ='
<Departments>
    <Department>
        <Employee>
            A
        </Employee>
        <Employee>
            B
        </Employee>
    </Department>

    <Department>
        <Employee>
            C
        </Employee>
        <Employee>
            D
        </Employee>
    </Department>
</Departments>';

--क्वेरी सीटीई का उपयोग संख्याओं को पहले स्तर पर बाँधने के लिए करेगी और आंतरिक नोड को संपूर्ण में पास करेगी। अंतिम चयन पास किए गए <Department> नोड का उपयोग करेगा और अपने कर्मचारियों को चुनेगा:

WITH NumberedDepartment AS
(
    SELECT ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) AS DepInx
          ,d.query(N'.') AS DepartmentNode
    FROM @myxml.nodes(N'/Departments/Department') AS A(d)
)
SELECT DepInx 
      ,e.value(N'text()[1]','nvarchar(max)') AS Employee
FROM NumberedDepartment
CROSS APPLY DepartmentNode.nodes(N'Department/Employee') AS B(e);

अगर आप सॉर्ट ऑर्डर की गारंटी के बारे में पढ़ना चाहते हैं तो आप इस थ्रेड को पढ़ सकते हैं। विशेष रूप से पढ़ने योग्य: नीचे दी गई बातचीत में जॉन कैपेलेटिस उत्तर देते हैं। वहां पर मैं XQuery का उपयोग करके एक दृष्टिकोण प्रदान करता हूं, और तत्वों को उनकी स्थिति में चुनने के लिए एक मिलान/संख्या तालिका का उपयोग करके एक और दृष्टिकोण प्रदान करता हूं। लेकिन यह बल्कि जटिल और धीमा है।

अद्यतन: गारंटीकृत सॉर्ट ऑर्डर के साथ एक दृष्टिकोण

यह दृष्टिकोण ऑन-द-फ्लाई एक मिलान तालिका तैयार करेगा। यदि आपके पास अंक तालिका है तो यह और भी बेहतर था...

TOP क्लॉज इस टैली को <Department> नोड्स की वास्तविक गणना तक सीमित कर देगा। एक स्रोत तालिका का उपयोग करना सुनिश्चित करें (मैं master..spt_values का उपयोग करता हूं) जिसमें कम से कम उतनी पंक्तियाँ हों जितनी आपको आवश्यकता हो सकती है।

प्रत्येक नंबर के लिए सही विभाग नोड प्राप्त करने के लिए पहला आवेदन .query() के साथ sql:column() का उपयोग करेगा। दूसरे आवेदन में संबंधित कर्मचारी पढ़ेंगे।

WITH Tally(Nmbr) AS
(
    SELECT TOP (SELECT @myxml.value(N'count(/Departments/Department)','int'))
           ROW_NUMBER() OVER(ORDER BY (SELECT NULL)) 
    FROM master..spt_values --just a pre-filled table with many rows
)
SELECT Nmbr
      ,e.value(N'text()[1]','nvarchar(max)') AS Employee
FROM Tally
OUTER APPLY(SELECT @myxml.query(N'/Departments/Department[sql:column("Nmbr")]')) AS A(ds)
OUTER APPLY ds.nodes(N'Department/Employee') AS B(e);
4
Community 20 जून 2020, 12:12