2011-10-19 20 views
9

में गतिशील कॉलम वाले पिवॉट्स मैं SQL सर्वर (टी-एसक्यूएल) में गतिशील कॉलम वाले पीवीओटी का उपयोग कर एक SQL क्वेरी पर काम कर रहा हूं। मेरी लंबी क्वेरी सबमिट करने के बजाय, मैं एक सरलीकृत मॉडल के साथ अपनी समस्या का वर्णन कर रहा हूं।एसक्यूएल सर्वर

2 टेबल बना: Table1 और तालिका 2 और इस प्रकार कुछ प्रविष्टियों के साथ उन्हें पॉप्युलेट:

Table1:


Col_ID1 ............ ... COL_NAME

1 ......................... जन-11

2 ........ ................. फरवरी -11

3 ......................... मार्च-11

तालिका 2:


Col_ID2 ...... खाता ..... खाता नाम ...... राशि

1 ............... 121 ......... .. इलेक्ट्रिकिटी ............ 10000

2 ............... 121 ........... बिजली। ........... 20000

3 ............... 121 ........... बिजली ............ 30000

1 ............... 122 ........... टेलीफोन .............. 100

2। .............. 122 ........... टेलीफोन .............. 200

3 ... ............ 122 ........... टेलीफोन .............. 300

मैं एक बना रहा हूँ पिवट, लेकिन मैं कॉलम नामों को पैरामीट्रिक रूप से जेनरेट करना चाहता हूं (इनपुट एस से की गई तिथियों के आधार पर क्रेन), और हार्ड कोडित नहीं है।

क्वेरी नीचे अच्छी तरह से काम करता है, लेकिन foll के रूप में केवल कुछ स्तंभों देता है:

जनवरी -11 ........... Feb-11 ........ ... मार्च-11

10,000.00 ...... 20,000.00 ...... 30,000.00

100,00 ............... 200.00 .... ....... 300.00

मैं चाहता हूं कि क्वेरी वर्णनात्मक कॉलम को भी वापस करे, जैसे कि foll:

खाता ........... खाता नाम ........... जनवरी -11 ............ फरवरी -11 .. ............ मार्च -11

121 ................. बिजली ............ ...... 10,000.00 ...... 20,000.00 .......... 30,000.00

122 ................. टेलीफोन .. ................... 100।00 ........... 200.00 ............. 300.00

क्या कोई मेरी मदद को संशोधित करने में मेरी सहायता कर सकता है ताकि मैं अपना उद्देश्य प्राप्त कर सकूं?

इस क्वेरी निम्न आलेख सितम्बर में डॉ एनड्रास द्वारा लिखित 2007. http://www.simple-talk.com/community/blogs/andras/archive/2007/09/14/37265.aspx

किसी ने टिप्पणी की है कि कोड इंजेक्शन हमलों के अधीन हो सकता है और बजाय Quotename फ़ंक्शन का उपयोग वर्ग कोष्ठक श्रृंखलाबद्ध करने का प्रस्ताव का रूपांतरण है ।

क्या आप मेरी क्वेरी में Quotename का उपयोग करने के तरीके की व्याख्या कर सकते हैं।

धन्यवाद एक बहुत,

लियोन लाइ ।

यहाँ मेरी क्वेरी है:

------------------------ बनाने & रूप से भरें table1 ---------- ----------------------

CREATE TABLE Table1 
(Col_ID1 INT, 
Col_Name varchar(10)) 

INSERT INTO Table1 VALUES (1, 'Jan-11') 
INSERT INTO Table1 VALUES (2, 'Feb-11') 
INSERT INTO Table1 VALUES (3, 'Mar-11') 

--------------------- ---- & रूप से भरें table2 ----------------------------------

CREATE TABLE Table2 
(Col_ID2 INT, 
Account varchar(10), 
AccountName varchar(20), 
Amount numeric(18,6)) 

INSERT INTO Table2 VALUES (1, 121, 'Electricity', 10000) 
INSERT INTO Table2 VALUES (2, 121, 'Electricity', 20000) 
INSERT INTO Table2 VALUES (3, 121, 'Electricity', 30000) 
INSERT INTO Table2 VALUES (1, 122, 'Telephone', 100)   
INSERT INTO Table2 VALUES (2, 122, 'Telephone', 200) 
INSERT INTO Table2 VALUES (3, 122, 'Telephone', 300) 

बना सकते हैं - --------------------------------- स्तंभ शीर्षलेख बनाएं -------------- -----

DECLARE @cols NVARCHAR(2000) 
SELECT @cols = STUFF((SELECT DISTINCT TOP 100 PERCENT 
'],[' + t2.Col_Name 
FROM Table1 AS t2 
ORDER BY '],[' + t2.Col_Name 
FOR XML PATH('') 
), 1, 2, '') + ']' 

------------------------------------- @query --- -------------------

DECLARE @query NVARCHAR(4000) 

SET @query = N'SELECT '+ 
@cols +' 

FROM 

------------------------ --subquery -----

(SELECT
t1.Col_Name,
t2.Account,
t2.Amount
FROM Table1 AS t1
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2
) p

-------------------- धुरी ------------ -------------

PIVOT
(
Sum ([Amount])
FOR Col_Name IN
('+
@cols +')
) AS pvt '

---------------------- कार्यकारी & ड्रॉप ----------

EXECUTE(@query) 
drop table table1 
drop table table2 

=== ================================================== ==

हाय फिलिप,

आपके उत्तर के लिए बहुत बहुत धन्यवाद।

आपकी प्रस्तावित क्वेरी सुचारू रूप से काम करती है, और अपेक्षित स्क्रीन उत्पन्न करती है, लेकिन यह वही नहीं है जो मैं चाहता था।

पहले, कोड के लिए धन्यवाद: चयन @cols = isnull (@cols + ',' ',') + '[' + COL_NAME + ']'

यह सरल है और मेरी लाइन की जगह है स्पष्ट रूप से एक ही प्रभाव के साथ सामान और एक्सएमएल पथ शामिल है।

मुझे बताएं कि मैं क्या करना चाहता हूं। (- या यह एक ERP फोन एक लेखा पैकेज)

मैं एसएपी बिजनेस 1 में एक प्रश्न विकसित करना चाहते हैं। सैप माइक्रोसॉफ्ट सर्वर 2008 में टी-एसक्यूएल का उपयोग करता है, और इसका अपना क्वेरी जनरेटर है। बहुत कम अपवादों के साथ, एसएपी एसक्यूएल टी-एसक्यूएल के समान है।

मैं चाहता हूं कि मेरी क्वेरी 12 महीने की अवधि में महीने में सभी आय और व्यय महीने की एक सूची दे।

हालांकि, मैं नहीं चाहता कि मेरे कॉलम शीर्षकों hardcoded किया जाना चाहते हैं, (के रूप में इस समय-समय पर अपनी क्वेरी में संशोधन करने के लिए मुझे की आवश्यकता होगी) इस प्रकार है:

जनवरी -11 फरवरी -11, Mar- 11, अप्रैल-11, ..... दिसम्बर-11

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

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

यही कारण है कि मैं @cols, @query, धुरी आदि के रूप में इस तरह के जटिल उपकरण की जरूरत

अगर मैं इनपुट, का कहना है कि '01 .06.11 '(01 जून 2011) इनपुट स्क्रीन में, इस तिथि हो जाएगा एसक्यूएल जो स्तंभ शीर्षकों के नाम का निर्धारण करेगा के रूप में foll को पारित:

जून 11, Jul-11 अगस्त -11 ..... मई-12।

मैं इनपुट एक और तारीख, कहते हैं '01 .09.10 '(01 सितं, 2010), स्तंभ शीर्षकों में परिवर्तित हो जाएगा:

सितम्बर 10, Oct-10, .... Aug-11

ऐसा लगता है कि आपने मेरे कॉलम शीर्षकों को हार्डकोड किया है।

आप अपनी क्वेरी में दूसरी बार नजर है, और कुछ है कि स्तंभ नाम के बजाय कठिन कोडित किया जा रहा parametrically उत्पन्न किया जा करने की अनुमति देगा का प्रस्ताव कर सकता है?

धन्यवाद

लियोन लाइ

उत्तर

11

उन स्तंभों जोड़ना बहुत आसान है। अंतिम क्वेरी

SELECT Account, AccountName, [Feb-11],[Jan-11],[Mar-11] FROM 
(SELECT 
t1.Col_Name, 
t2.Account, 
t2.AccountName, 
t2.Amount 
FROM Table1 AS t1 
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2 
) p 
PIVOT 
(
Sum ([Amount]) 
FOR Col_Name IN 
([Feb-11],[Jan-11],[Mar-11]) 
) AS pvt 

जो t2.AccountName सबक्वेरी को जोड़ा गया होगा, और खाते और AccountName प्रारंभिक चयन करने के लिए जोड़ा। उन्हें निर्माण बयान में टॉस और आपका काम हो:

DECLARE @query NVARCHAR(4000) 
SET @query = N'SELECT Account, AccountName, ' + @cols +' FROM 

(SELECT 
t1.Col_Name, 
t2.Account, 
t2.AccountName, 
t2.Amount 
FROM Table1 AS t1 
JOIN Table2 AS t2 ON t1.Col_ID1 = t2.Col_ID2 
) p 

PIVOT 
(
Sum ([Amount]) 
FOR Col_Name IN 
('+ 
@cols +') 
) AS pvt ' 

एसक्यूएल इंजेक्शन, एक ही रास्ता मैं देख सकता हूँ कि क्या हो रहा है, तो किसी को किसी भी तरह Table1.Col_Name के दुर्भावनापूर्ण कोड एम्बेड करता है का सवाल है, और यदि आप चिंता करने की ज़रूरत इसके बारे में, आपको इस गतिशील क्वेरी को "लॉक डाउन" करने से बड़ी समस्याएं हैं।

इसके अलावा उल्लेख के लायक है, मैं कॉलम (@Cols) क्योंकि इसके छोटी और पढ़ने में आसान है, लेकिन ज्यादातर क्योंकि मुझे पसंद नहीं है एक्सएमएल की सूची बनाने के लिए निम्नलिखित का उपयोग करेंगे।

DECLARE @cols NVARCHAR(2000)  
SELECT @cols = isnull(@cols + ',', '') + '[' + Col_Name + ']' 
FROM Table1 
ORDER BY Col_Name 
+0

हाय फिलिप, मैंने आपके उत्तर में एक प्रश्न पोस्ट किया धन्यवाद धन्यवाद लियोन –

+0

यह एक हास्यास्पद अच्छा जवाब है !!! – jTC

+0

''' '' Col_Name + ']'' के बजाय 'quotename (Col_Name) 'का उपयोग करें। – jnm2

1

एक और जवाब जोड़ना, क्योंकि यह लगभग एक दूसरा प्रश्न संपादित करता है। (विवरण और विनिर्देशों के बिना, मैं केवल सामान्य रूपरेखा और psuedo कोड प्रदान कर सकता हूं- मुझे एसएपी नहीं पता है।)

चलो पिवट के साथ शुरू करते हैं। इसे संभावित रूप से, महीने के लेबल वाले कॉलम जेनरेट करने की आवश्यकता है, जो आपके उदाहरण में table1.Col_Name, एक वर्चर (10) के रूप में था; उन मान निकाले गए हैं और गतिशील रूप से स्तंभ नाम के रूप में स्तंभ नाम के रूप में जोड़े गए हैं। यदि डेटाबेस में ऐसा कोई स्तंभ नहीं है, तो आपको उपयोगकर्ता द्वारा दर्ज किए गए डेटा के आधार पर क्वेरी के लिए इसे बनाना होगा। मैं निम्नलिखित मान्यताओं के साथ काम करूंगा: - डेटा में एक दिनांक कॉलम है, जहां कोई मान (मिलीसेकंड के माध्यम से वर्ष) पाया जा सकता है - उपयोगकर्ता "प्रारंभ तिथि" निर्दिष्ट करता है (क्या यह हमेशा एक महीने का पहला होता है?) और आपको उस लक्ष्य के लिए कॉलम उत्पन्न करना होगा और निम्नलिखित 11 महीनों में, प्रत्येक लक्ष्य माह में आने वाले डेटा को एकत्रित करना होगा।

चरण 1, मैं की स्थापना की और 12 लक्ष्य कॉलम युक्त एक अस्थायी तालिका पॉप्युलेट चाहते हैं:

CREATE TABLE #Months 
(
    Col_Name varchar(10) 
    ,MonthStart datetime 
    ,MonthEnd datetime 
) 

लेबल के रूप में आप यह दिखाना चाहते हैं स्वरूपित है, MonthStart महीने के निरपेक्ष शुरुआत होगी (कहें, 1 अक्टूबर, 2011 00: 00: 00.000), और महीना अंत अगले महीने की पूर्ण शुरुआत होगी (1 नवंबर, 2011 00: 00: 00.000) - इससे आपको उस महीने के भीतर सभी डेटा प्राप्त करने के लिए SELECT … from <table> where DataDate >= MontStart and DataDate < MonthEnd का उपयोग करने की अनुमति मिलती है।

इसके बाद, अपने डेटा तालिका और कुल, की तरह कुछ पर इस तालिका में शामिल होने:

SELECT 
    mt.Col_Name 
    ,sum(dt.RawData) Amount 
from #Months mt 
    inner join MyData dt 
    on dt.DataDate >= mt.MonthStart 
    and dt.DataDate < mt.MonthEnd -- Yes, ON clauses don't have to be simple equivalencies! 
    inner join <other tables as necessary for Account, AccountName, etc.> 

प्लग इस में धुरी बयान के अंतरतम क्वेरी, निकालने/Col_Names की सूची अस्थायी मेज से का उपयोग कर निर्माण के रूप में गैर-एक्सएमएल क्वेरी (मुझे नहीं पता कि इसे और क्या कहें), गतिशील रूप से निर्माण और निष्पादित करें, और आपको अच्छा होना चाहिए।

+0

धन्यवाद फिलिप लियोन लाई –