Sqlserver
 sql >> डेटाबेस >  >> RDS >> Sqlserver

इस तालिका की जानकारी को उपयोग में आसान फॉर्म में कैसे बदलें?

(थोड़ा रुग्ण) जिज्ञासा से मैंने आपके द्वारा प्रदान किए गए सटीक इनपुट डेटा को बदलने के साधन के साथ आने की कोशिश की।

बेशक, मूल डेटा को ठीक से व्यवस्थित करना बेहतर होगा। एक विरासती प्रणाली के साथ, यह संभव नहीं हो सकता है, लेकिन इस जानकारी को एक मध्यवर्ती स्थान पर लाने के लिए एक ईटीएल प्रक्रिया बनाई जा सकती है ताकि इस तरह की एक बदसूरत क्वेरी को वास्तविक समय में चलाने की आवश्यकता न हो।

उदाहरण #1

यह उदाहरण मानता है कि सभी आईडी सुसंगत और अनुक्रमिक हैं (अन्यथा, एक अतिरिक्त ROW_NUMBER() आईडी पर सही शेष संचालन की गारंटी के लिए कॉलम या एक नए पहचान कॉलम का उपयोग करने की आवश्यकता होगी)।

SELECT
    Name = REPLACE( Name, 'name: ', '' ),
    Age = REPLACE( Age, 'age: ', '' )
FROM
(
    SELECT
        Name = T2.Data,
        Age = T1.Data,
        RowNumber = ROW_NUMBER() OVER( ORDER BY T1.Id ASC )

    FROM @t T1 
        INNER JOIN @t T2 ON T1.id = T2.id +1 -- offset by one to combine two rows
    WHERE T1.id % 3 != 0 -- skip delimiter records
) Q1
 -- skip every other record (minus delimiters, which have already been stripped)
WHERE RowNumber % 2 != 0

उदाहरण #2:अनुक्रमिक आईडी पर कोई निर्भरता नहीं

यह एक अधिक व्यावहारिक उदाहरण है क्योंकि वास्तविक आईडी मान मायने नहीं रखते, केवल पंक्ति अनुक्रम।

DECLARE @NumberedData TABLE( RowNumber INT, Data VARCHAR( 100 ) );

INSERT @NumberedData( RowNumber, Data )
    SELECT 
        RowNumber = ROW_NUMBER() OVER( ORDER BY id ASC ),
        Data
    FROM @t;

SELECT 
    Name = REPLACE( N2.Data, 'name: ', '' ),
    Age = REPLACE( N1.Data, 'age: ', '' ) 
FROM @NumberedData N1 
    INNER JOIN @NumberedData N2 ON N1.RowNumber = N2.RowNumber + 1
WHERE ( N1.RowNumber % 3 ) = 2;

DELETE @NumberedData;

उदाहरण #3:कर्सर

फिर से, इस तरह की क्वेरी को वास्तविक समय में चलाने से बचना और एक निर्धारित, लेन-देन संबंधी ईटीएल प्रक्रिया का उपयोग करना सबसे अच्छा होगा। मेरे अनुभव में, इस तरह का अर्ध-संरचित डेटा विसंगतियों से ग्रस्त है।

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

-- this could be a table variable, temp table, or staging table
DECLARE @Results TABLE ( Name VARCHAR( 100 ), Age INT );

DECLARE @Index INT = 0, @Data VARCHAR( 100 ), @Name VARCHAR( 100 ), @Age INT;

DECLARE Person_Cursor CURSOR FOR SELECT Data FROM @t;
OPEN Person_Cursor;
FETCH NEXT FROM Person_Cursor INTO @Data;

WHILE( 1 = 1 )BEGIN -- busy loop so we can handle the iteration following completion
    IF( @Index = 2 ) BEGIN
        INSERT @Results( Name, Age ) VALUES( @Name, @Age );
        SET @Index = 0;
    END
    ELSE BEGIN
            -- optional: examine @Data for integrity

        IF( @Index = 0 ) SET @Name = REPLACE( @Data, 'name: ', '' );
        IF( @Index = 1 ) SET @Age = CAST( REPLACE( @Data, 'age: ', '' ) AS INT );
        SET @Index = @Index + 1;
    END

    -- optional: examine @Index to see that there are no superfluous trailing 
    -- rows or rows omitted at the end.

    IF( @@FETCH_STATUS != 0 ) BREAK;
    FETCH NEXT FROM Person_Cursor INTO @Data;
END

CLOSE Person_Cursor;
DEALLOCATE Person_Cursor;

प्रदर्शन

मैंने 100K पंक्तियों का नमूना स्रोत डेटा बनाया है और उपरोक्त तीन उदाहरण डेटा बदलने के लिए लगभग बराबर लगते हैं।

मैंने स्रोत डेटा की एक लाख पंक्तियाँ बनाईं और निम्न के समान एक क्वेरी पंक्तियों के सबसेट को चुनने के लिए उत्कृष्ट प्रदर्शन देती है (जैसे कि वेब पेज या रिपोर्ट पर ग्रिड में उपयोग किया जाएगा)।

-- INT IDENTITY( 1, 1 ) numbers the rows for us
DECLARE @NumberedData TABLE( RowNumber INT IDENTITY( 1, 1 ), Data VARCHAR( 100 ) );

-- subset selection; ordering/filtering can be done here but it will need to preserve
-- the original 3 rows-per-result structure and it will impact performance
INSERT @NumberedData( Data )
    SELECT TOP 1000 Data FROM @t;

SELECT
    N1.RowNumber,
    Name = REPLACE( N2.Data, 'name: ', '' ),
    Age = REPLACE( N1.Data, 'age: ', '' ) 
FROM @NumberedData N1 
    INNER JOIN @NumberedData N2 ON N1.RowNumber = N2.RowNumber + 1
WHERE ( N1.RowNumber % 3 ) = 2;

DELETE @NumberedData;

मैं एक लाख रिकॉर्ड के सेट के मुकाबले 4-10ms (i7-3960x) का निष्पादन समय देख रहा हूं।



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. SQL सर्वर में 'पिवट' का उपयोग करके पंक्तियों को कॉलम में बदलें

  2. SQL सर्वर डायग्नोस्टिक्स चलाने के लिए 4 युक्तियाँ

  3. प्रोफाइलर में एसक्यूएल छुपाएं

  4. फ़ंक्शन में SQL सर्वर में अल्पविराम सीमांकित मानों से भरा एक वर्चर पास करना

  5. एसक्यूएल सर्वर 4 बाइट अहस्ताक्षरित int