मूल पिवट ऑपरेटर पर मेरे पिछले लेख में, हमने देखा कि पंक्तियों को कॉलम में बदलने के लिए पिवट ऑपरेटर का उपयोग कैसे किया जा सकता है, जिसके परिणामस्वरूप पिवट टेबल होते हैं। हमने देखा कि पिवट टेबल बनाने के तीन मुख्य चरण थे। पहला कदम आधार डेटा का चयन करना था। दूसरा चरण बेस डेटा को टेबल-वैल्यू एक्सप्रेशन में बदलना था, और अंतिम चरण में पिवट ऑपरेटर को अस्थायी डेटा पर लागू करना शामिल था, जिसके परिणामस्वरूप पिवट तालिका बन गई।
नीचे दिए गए उदाहरण पर एक नज़र डालें।
USE schooldb SELECT * FROM (SELECT city, total_score FROM student ) AS StudentTable PIVOT( AVG(total_score) FOR city IN ([London],[Liverpool],[Leeds],[Manchester]) ) AS StudentPivotTable
नोट: डमी डेटाबेस और डेटा बनाने के लिए, पिवट ऑपरेटर पर पिछला लेख देखें।
पिवट ऑपरेटर की सीमाएं
हालाँकि, पिवट ऑपरेटर की कुछ सीमाएँ हैं। पिवट ऑपरेटर के अंदर, हमें उस कुल फ़ील्ड और कॉलम को निर्दिष्ट करना होगा, जिस पर हम अपना डेटा पिवट करना चाहते हैं। अंत में, हमें उन कॉलम शीर्षकों के लिए अलग-अलग मान भी सेट करने होंगे जिन्हें हम बनाना चाहते हैं।
यदि हम पिछले भाग से स्क्रिप्ट निष्पादित करते हैं, तो हमें निम्नलिखित परिणाम प्राप्त होंगे:
[टेबल आईडी=35 /]
कॉलम के शीर्षक शहर के कॉलम के अंदर अलग-अलग मान हैं। हमने अपनी क्वेरी में इन मानों को पिवट ऑपरेटर के अंदर निर्दिष्ट किया है।
पिवट टेबल बनाने का सबसे कठिन हिस्सा कॉलम हेडिंग के लिए मैन्युअल रूप से मान निर्दिष्ट करना है। यह वह हिस्सा है जो अधिकांश त्रुटियों से ग्रस्त है, खासकर यदि आपके ऑनलाइन डेटा स्रोत में डेटा बदलता है। हम यह सुनिश्चित नहीं कर सकते हैं कि पिवट ऑपरेटर में निर्दिष्ट मान डेटाबेस में तब तक रहेंगे जब तक हम अगली बार यह पिवट तालिका नहीं बनाते।
उदाहरण के लिए, हमारी लिपि में, हमने लंदन, लिवरपूल, लीड्स और मैनचेस्टर को अपनी पिवट टेबल के शीर्षकों के लिए मान के रूप में निर्दिष्ट किया है। ये मान छात्र तालिका के ity कॉलम में मौजूद थे। क्या होगा यदि किसी तरह इनमें से एक या अधिक मान हटा दिए गए या अपडेट किए गए? ऐसे मामलों में, शून्य वापस कर दिया जाएगा।
एक बेहतर तरीका यह होगा कि एक डायनामिक क्वेरी बनाई जाए जो उस कॉलम से मानों का एक पूरा सेट लौटाए जिससे आप अपनी पिवट टेबल बनाने की कोशिश कर रहे हैं।
डायनामिक पिवट टेबल बनाना
इस खंड में, हम देखेंगे कि एक गतिशील पिवट तालिका कैसे बनाई जाती है।
इसका मतलब है कि हमें उस कॉलम के लिए मैन्युअल रूप से मान निर्दिष्ट करने की आवश्यकता नहीं होगी जिससे हम अपनी पिवट टेबल बनाने की कोशिश कर रहे हैं। इसके बजाय, हम इन मानों को गतिशील रूप से सेट करेंगे। इस उद्देश्य के लिए, हम "QUOTENAME" फ़ंक्शन का उपयोग करेंगे।
हमेशा की तरह, नए कोड के साथ प्रयोग करने से पहले सुनिश्चित करें कि आपने अच्छी तरह से बैकअप लिया है। यदि आप सुनिश्चित नहीं हैं तो MS SQL डेटाबेस के बैकअप पर यह लेख देखें।
QUOTENAME फ़ंक्शन
"QUOTENAME" फ़ंक्शन चयनित परिणामों को प्रारूपित करता है। डायनामिक पिवट की व्याख्या करने से पहले यह "QUOTENAME" फ़ंक्शन के त्वरित कार्यशील उदाहरण को देखने लायक है।
निम्न क्वेरी पर एक नज़र डालें।
USE schooldb SELECT QUOTENAME(city)+ ',' FROM student
डिफ़ॉल्ट रूप से, "QUOTENAME" फ़ंक्शन चयनित आइटम को वर्गाकार कोष्ठकों में लपेटता है। उपरोक्त क्वेरी का आउटपुट इस तरह दिखता है:
[टेबल आईडी=36 /]
कॉलम नामों को एक चर में संग्रहीत करना
हालांकि हमने स्तंभ मानों को वर्गाकार कोष्ठकों में लपेटा है, हमें इस प्रारूप में पिवट ऑपरेटर में मान निर्दिष्ट करने की आवश्यकता है:
"[लीड्स], [लिवरपूल], [लंदन], [मैनचेस्टर]"
ऐसा करने के लिए, हमें एक चर की आवश्यकता होगी।
USE schooldb DECLARE @CityNames NVARCHAR(MAX) = '' SELECT @CityNames += QUOTENAME(city)+ ',' FROM ( SELECT DISTINCT city FROM student ) AS CITIES PRINT @CityNames
उपरोक्त क्वेरी में, हमने एक वैरिएबल "@CityNames" घोषित किया और इसे एक खाली स्ट्रिंग के साथ इनिशियलाइज़ किया। फिर, हमने शहर के कॉलम से अलग-अलग शहर के नामों का चयन करने के लिए एक सेलेक्ट स्टेटमेंट का उपयोग किया और उन्हें "@CityNames" वेरिएबल में स्टोर किया। प्रत्येक पुनरावृत्ति में, शहर के कॉलम में अल्पविराम के साथ एक विशिष्ट मान "@CityNames" चर में जोड़ा जाएगा।
फिर, हमने इस वेरिएबल में संग्रहीत मान को प्रिंट किया। उपरोक्त क्वेरी का परिणाम इस तरह दिखेगा:
"[लीड्स], [लिवरपूल], [लंदन], [मैनचेस्टर],"
यदि आप आउटपुट को देखते हैं, तो अंतिम मान के बाद अल्पविराम होता है। हमें इसकी आवश्यकता नहीं है।
एक पिछला कॉमा हटाना
एक अनुगामी अल्पविराम को हटाने के लिए, हम एक LEFT फ़ंक्शन का उपयोग करेंगे जो एक स्ट्रिंग को इसके पहले तर्क के रूप में लेता है। दूसरा तर्क उस स्ट्रिंग से पहले वर्ण से शुरू होने वाले वर्णों की संख्या है। निम्न क्वेरी पर एक नज़र डालें:
USE schooldb DECLARE @CityNames NVARCHAR(MAX) = '' SELECT @CityNames += QUOTENAME(city)+ ',' FROM ( SELECT DISTINCT city FROM student ) AS CITIES SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1) PRINT @CityNames
यहाँ स्क्रिप्ट की इस पंक्ति पर ध्यान दें:
SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1)
स्क्रिप्ट की इस पंक्ति में, हमने पहले तत्व से शुरू करके "@CityNames" चर में संग्रहीत मान के बाईं ओर के सभी वर्णों को प्राप्त करने के लिए LEFT फ़ंक्शन का उपयोग किया। दूसरे तर्क में, हमने "@CityNames" फ़ंक्शन में संग्रहीत मान तत्वों की संख्या की गणना करने के लिए LEN फ़ंक्शन का उपयोग किया और अंत में, हमने इसमें से 1 घटा दिया। यह स्ट्रिंग से अनुगामी अल्पविराम को हटा देता है। आउटपुट इस तरह दिखेगा:
[लीड्स], [लिवरपूल], [लंदन], [मैनचेस्टर]
SQL क्वेरी को स्ट्रिंग में कनवर्ट करना
अब, उम्मीद है, हम अपने पिवट ऑपरेटर के अंदर "@CityNames" वेरिएबल का उपयोग इस तरह कर सकते हैं:
PIVOT( AVG(total_score) FOR city IN ( @CityNames )
हालाँकि, हम अपने पिवट ऑपरेटर के अंदर एक चर का उपयोग नहीं कर सकते। वैकल्पिक तरीका हमारी पूरी SQL क्वेरी को एक स्ट्रिंग में बदलना है। इस स्ट्रिंग के अंदर, हम अपने “@CityNames” वेरिएबल को हुक करेंगे।
USE schooldb DECLARE @CityNames NVARCHAR(MAX) = '' DECLARE @Query NVARCHAR(MAX) = '' SELECT @CityNames += QUOTENAME(city)+ ',' FROM ( SELECT DISTINCT city FROM student ) AS CITIES SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1) SET @Query = 'SELECT * FROM (SELECT city, total_score FROM student ) AS StudentTable PIVOT( AVG(total_score) FOR city IN (' + @CityNames +') ) AS StudentPivotTable' PRINT @Query
यहां हमने एक वेरिएबल "@Query" घोषित किया और इस वेरिएबल में हमारी SQL क्वेरी को स्टोर किया। पिवट ऑपरेटर के अंदर, हमने "@CityNames" वेरिएबल के अंदर संग्रहीत मान को जोड़ दिया। यह देखने के लिए कि निष्पादित क्वेरी कैसी दिखती है, हमने "@Query" चर का मान मुद्रित किया है। परिणामी क्वेरी आउटपुट में इस तरह दिखेगी:
SELECT * FROM (SELECT city, total_score FROM student ) AS StudentTable PIVOT( AVG(total_score) FOR city IN ([Leeds],[Liverpool],[London],[Manchester]) ) AS StudentPivotTable
यह ठीक उसी प्रकार की क्वेरी है जिसे हम निष्पादित करना चाहते हैं। हालाँकि, यह स्ट्रिंग प्रारूप में है। टेक्स्ट स्ट्रिंग के रूप में संग्रहीत इस SQL क्वेरी को निष्पादित करने के लिए अंतिम चरण है। ऐसा करने के लिए, हम डायनेमिक SQL का उपयोग करेंगे।
डायनामिक SQL का निष्पादन
हम डायनेमिक SQL को निष्पादित करने के लिए अंतर्निहित प्रक्रिया "sp_executesql" का उपयोग करते हैं। हम इस संग्रहीत कार्यविधि का उपयोग @Query चर में संग्रहीत क्वेरी को निष्पादित करने के लिए करेंगे। गतिशील पिवट तालिका बनाने वाली हमारी अंतिम क्वेरी इस तरह दिखती है:
USE schooldb DECLARE @CityNames NVARCHAR(MAX) = '' DECLARE @Query NVARCHAR(MAX) = '' SELECT @CityNames += QUOTENAME(city)+ ',' FROM ( SELECT DISTINCT city FROM student ) AS CITIES SET @CityNames = LEFT(@CityNames, LEN(@CityNames)-1) SET @Query = 'SELECT * FROM (SELECT city, total_score FROM student ) AS StudentTable PIVOT( AVG(total_score) FOR city IN (' + @CityNames +') ) AS StudentPivotTable' EXECUTE sp_executesql @Query
जब आप उपरोक्त क्वेरी को निष्पादित करते हैं, तो आपको निम्न परिणाम देखना चाहिए:
[टेबल आईडी=37 /]
हालाँकि, इस बार, हमने पिवट तालिका के शीर्षकों के लिए मानों को मैन्युअल रूप से निर्दिष्ट नहीं किया है। इसके बजाय, शीर्षकों की गणना गतिशील रूप से की गई है जिसके परिणामस्वरूप एक गतिशील पिवट तालिका बनती है।