2012-04-30 6 views
11

मैंने इस क्वेरी को एक तालिका से सीमांकित सूची बनाने के लिए Google की मदद से लिखा है लेकिन मुझे इस क्वेरी से कुछ भी समझ में नहीं आया।अल्पविराम सीमांकित सूची SQL सर्वर बनाने के लिए यह क्वेरी क्या करती है?

किसी को भी मुझे बता सकते हैं क्या हो रहा है

SELECT 
    E1.deptno, 
    allemp = Replace ((SELECT E2.ename AS 'data()' 
         FROM emp AS e2 
         WHERE e1.deptno = e2.DEPTNO 
         FOR xml PATH('')), ' ', ', ') 
FROM EMP AS e1 
GROUP BY DEPTNO; 

देता है मुझे परिणाम

10 CLARK, KING, MILLER 
20 SMITH, JONES, SCOTT, ADAMS, FORD 
30 ALLEN, WARD, MARTIN, BLAKE, TURNER, JAMES 
+1

** कृपया ध्यान दें, जो आपके कोड की तरह पाठ वाले पात्रों के लिए विफल होगा><& ** आप '' <, जैसे चरित्र विस्तार मिल जाएगा '>' '' & इस संयोजन करने के लिए एक बेहतर तरीका है, देखें: http://stackoverflow.com/a/5031297/65223 –

उत्तर

35

यह समझाने का सबसे आसान तरीका यह है कि FOR XML PATH वास्तविक XML के लिए कैसे काम करता है।एक साधारण तालिका Employee कल्पना कीजिए:

EmployeeID  Name 
1    John Smith 
2    Jane Doe 

आप इस्तेमाल कर सकते हैं के रूप में PATH से 'कर्मचारी' निकाला जा रहा है

<Employee> 
    <EmployeeID>1</EmployeeID> 
    <Name>John Smith</Name> 
</Employee> 
<Employee> 
    <EmployeeID>2</EmployeeID> 
    <Name>Jane Doe</Name> 
</Employee> 

इस प्रकार

SELECT EmployeeID, Name 
FROM emp.Employee 
FOR XML PATH ('Employee') 

यह XML बन जाएगा यह तो बाहरी एक्सएमएल टैग को हटा क्वेरी:

SELECT Name 
FROM Employee 
FOR XML PATH ('') 

<Name>John Smith</Name> 
    <Name>Jane Doe</Name> 

क्या आप तो कर रहे हैं आदर्श नहीं है बनाने चाहेंगे, स्तंभ नाम 'डेटा()' एक एसक्यूएल त्रुटि है क्योंकि यह एक xml टैग जो एक कानूनी टैग नहीं है बनाने के लिए कोशिश कर रहा है मजबूर करता है, तो निम्न त्रुटि उत्पन्न होती है:

कॉलम नाम 'डेटा()' में XML के लिए आवश्यक एक अवैध XML पहचानकर्ता शामिल है; '(' (0x0028) की गलती पहले वर्ण है

सहसंबद्ध सबक्वेरी इस त्रुटि को छुपाता है और सिर्फ कोई टैग के साथ एक्सएमएल उत्पन्न करता है:।

SELECT Name AS [Data()] 
FROM Employee 
FOR XML PATH ('') 

बनाता

John Smith Jane Doe 

आप फिर कॉमा के साथ रिक्त स्थान बदल रहे हैं, काफी आत्म व्याख्यात्मक ...

यदि मैं आप थे तो मैं क्वेरी को थोड़ा सा अनुकूलित कर दूंगा:

SELECT E1.deptno, 
     STUFF((SELECT ', ' + E2.ename 
       FROM emp AS e2 
       WHERE e1.deptno = e2.DEPTNO 
       FOR XML PATH('') 
      ), 1, 2, '') 
FROM EMP AS e1 
GROUP BY DEPTNO; 

त्रुटियों का कारण नहीं बनेगा में होने कोई स्तंभ उर्फ ​​कोई एक्सएमएल टैग बनाई गई हैं मतलब होगा, और चयन क्वेरी में अल्पविराम जोड़ने का मतलब है रिक्त स्थान के साथ किसी भी नाम, STUFF पहले अल्पविराम और अंतरिक्ष को हटा देगा।

परिशिष्ट

, क्या के.एम. एक टिप्पणी में कहा है पर विस्तार से बता दें क्योंकि इसमें कुछ अधिक देखा जा रहा है किया जा रहा है, एक्सएमएल पात्रों से बचने के लिए सही तरीका इस प्रकार .value उपयोग करने के लिए होगा:

SELECT E1.deptno, 
     STUFF((SELECT ', ' + E2.ename 
       FROM emp AS e2 
       WHERE e1.deptno = e2.DEPTNO 
       FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') 
FROM EMP AS e1 
GROUP BY DEPTNO; 
+1

बहुत अच्छी व्याख्या आपको धन्यवाद! –

+3

+1 अच्छा स्पष्टीकरण, लेकिन ** कृपया ध्यान दें कि इस कोड में पाठकों को शामिल करने के लिए विफल होगा><& ** आपको चरित्र विस्तार जैसे '<', '>' '& 'इस संगतता को करने का एक बेहतर तरीका है , देखें: http://stackoverflow.com/a/5031297/65223 –

+1

आप 'NVARCHAR (MAX)' ' – wilsjd

0

बाहरी क्वेरी विभाग नंबरों की सूची प्राप्त करता है, और सबक्वेरी तो प्रत्येक विभाग नंबर सब वापस जाने के लिए के लिए चलाया जाता है उस विभाग से संबंधित नाम। सबक्वायरी आउटपुट को एक सिंगल लाइन अल्पविराम से अलग सूची में प्रारूपित करने के लिए एक्सएमएल स्टेटमेंट का उपयोग करता है।

6

इसे अंदर से बाहर - चरण-दर-चरण ले जाएं।

चरण 1:

भागो अंतरतम क्वेरी और देखें कि यह क्या पैदा करता है:

CLARK KING MILLER 

चरण 2::

SELECT E2.ename AS 'data()' 
FROM emp AS e2 
WHERE e2.DEPTNO = 10 
FOR XML PATH('') 

आप की तरह एक निर्गम कुछ मिलना चाहिए

REPLACE सिर्फ , साथ रिक्त स्थान को बदल देता है - इस प्रकार में

CLARK, KING, MILLER 

चरण अपने उत्पादन मोड़ 3:

बाहरी क्वेरी हो जाता है deptno मूल्य - प्लस आंतरिक क्वेरी से परिणाम - और अपने अंतिम पैदा करता है परिणाम।

1

SQL सर्वर 2017new STRING_AGG के साथ यह बहुत आसान बनाता है। हाल ही में इस पोस्ट में आया और नए स्ट्रिंग फ़ंक्शन का उपयोग करने के लिए मेरी STUFF/XML रणनीति के लिए स्विच किया। एक्सएम एक्सएमएल (और अजीब-एन्कोडिंग मुद्दों) के अतिरिक्त अतिरिक्त जॉइन/सबक्वायर और ओवरहेड करने की आवश्यकता से बचाता है और एसक्यूएल की व्याख्या करना मुश्किल है।

SELECT E1.deptno, 
     STRING_AGG(E1.ename, ', ') AS allemp 
FROM EMP AS e1 
GROUP BY DEPTNO; 

नोट: इसके अलावा एसक्यूएल सीमांकित डेटा के साथ काम करने के लिए बहुत आसान बनाने के लिए check out the counterpart STRING_SPLIT कर लें।

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