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

डायनामिक अनपिवट और स्प्लिट कॉलम SQL सर्वर 2012

UNPIVOT कुछ इस तरह:

WITH Unpivoted 
AS
(
    SELECT region, lob, columns, value
    FROM Regions
    UNPIVOT
    (
       columns
       FOR value IN([GWP 2013] , [GWP 2014] ,
                    [LR 2013]  , [LR 2014] ,
                    [GWP 2015], [LR 2015])
    ) AS u
) 
SELECT 
  region, 
  lob,
  columns,
  CAST(CASE WHEN value LIKE 'GWP%' THEN REPLACE(value,'GWP ', '')
       WHEN value LIKE 'LR%' THEN REPLACE(value,'LR ', '')
  END AS INT) AS Year,
  CASE WHEN value LIKE 'GWP%' THEN 'GWP'
       WHEN value LIKE 'LR%' THEN 'LR'
  END AS Metrics
FROM Unpivoted;

और फिर निश्चित रूप से आपको कॉलम को मैन्युअल रूप से सूचीबद्ध करने से बचने के लिए इसे गतिशील रूप से करना चाहिए और इसे गतिशील रूप से करना चाहिए:

DECLARE @cols AS NVARCHAR(MAX);
DECLARE @query AS NVARCHAR(MAX);

select @cols = STUFF((SELECT distinct ',' +
                        QUOTENAME(column_name)
                      FROM information_schema.columns
                      WHERE table_name = 'Regions'
                        AND COLUMN_NAME <> 'Region' 
                        AND COLUMN_NAME <> 'LOB'
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');


SELECT @query = 'WITH Unpivoted 
                AS
                (
                    SELECT region, lob, columns, value
                    FROM Regions
                    UNPIVOT
                    (
                       columns
                       FOR value IN('+ @cols + ')
                    ) AS u
                ) 
                SELECT 
                  region, 
                  lob,
                  columns,
                  CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
                       WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
                  END AS INT) AS Year,
                  CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
                       WHEN value LIKE ''LR%'' THEN ''LR''
                  END AS Metrics
                FROM Unpivoted';


EXECUTE(@query);

यह मानकर ठीक काम करना चाहिए कि:

  • सभी कॉलम [GWP 2013] , [GWP 2014] , [LR 2013] , [LR 2014] , [GWP 2015], [LR 2015], ... etc एक ही प्रारूप में हैं (जीडब्ल्यूपी या एलआर फिर स्थान फिर वर्ष, और
  • सभी कॉलम एक ही डेटा प्रकार के होते हैं int या दशमलव, यदि डेटा प्रकार समान नहीं हैं, तो unpivot करने से पहले आपको उन सभी को एक डेटा प्रकार में डालना चाहिए अन्यथा आपको एक त्रुटि मिलेगी।

  • एसक्यूएल फिडल डेमो

यह आपको देगा:

| region |     lob |  columns | Year | Metrics |
|--------|---------|----------|------|---------|
|  North | Workers |  38902.5 | 2013 |     GWP |
|  North | Workers | 37972404 | 2014 |     GWP |
|  North | Workers |       70 | 2015 |     GWP |
|  North | Workers |       89 | 2013 |      LR |
|  North | Workers |       82 | 2014 |      LR |
|  North | Workers |       80 | 2015 |      LR |

अपडेट करें:

मैंने FOR XML PATH('') .. एक स्ट्रिंग में मानों की सभी सूची को संयोजित करने के लिए, ऐसा करने के लिए SQL सर्वर में यह एक कार्य है। @cols . का मान स्ट्रिंग होगी:[GWP 2013], [GWP 2014], ...

यदि आपके फ़ील्ड डेटा प्रकार भिन्न हैं, तो आपको UNPVOT करने से पहले उन सभी कॉलमों की कास्ट करनी होगी जो एंकर क्वेरी में अनपिवट किए जाएंगे। इस तरह:

SELECT @query = 'WITH Unpivoted 
                AS
                (
                    SELECT region, lob, columns, value
                    FROM 
                    (
                       SELECT 
                         region,
                         lob,
                         CAST([GWP 2013] AS DECIMAL(10,2)) AS [GWP 2013],
                         CAST([GWP 2014] AS DECIMAL(10,2)) AS [GWP 2014],
                         ... etc
                       FROM Regions
                    ) AS t
                    UNPIVOT
                    (
                       columns
                       FOR value IN('+ @cols + ')
                    ) AS u
                ) 
                SELECT 
                  region, 
                  lob,
                  columns,
                  CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
                       WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
                  END AS INT) AS Year,
                  CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
                       WHEN value LIKE ''LR%'' THEN ''LR''
                  END AS Metrics
                FROM Unpivoted';

यदि आपको मैन्युअल रूप से सभी स्तंभों के लिए कास्ट लिखना कठिन लगता है, तो आप इसे गतिशील रूप से उत्पन्न कर सकते हैं और इसके बजाय इसे जोड़ सकते हैं, उदाहरण के लिए:

DECLARE @colsCasted AS NVARCHAR(MAX);

select @colsCasted = STUFF((SELECT distinct ',' +
                        'CAST(' + QUOTENAME(column_name) + 'AS DECIMAL(10,2)) AS ' + QUOTENAME(column_name)
                      FROM information_schema.columns
                      WHERE table_name = 'Regions'
                        AND COLUMN_NAME <> 'Region' 
                        AND COLUMN_NAME <> 'LOB'
                      FOR XML PATH(''), TYPE
                     ).value('.', 'NVARCHAR(MAX)') 
                        , 1, 1, '');

फिर डायनेमिक क्वेरी में उस मान को इसमें जोड़ें:

SELECT @query = 'WITH Unpivoted 
                    AS
                    (
                        SELECT region, lob, columns, value
                        FROM 
                        (
                          SELECT region, lob,
                          ' + @colsCasted + '
                          FROM Regions
                        ) AS t
                        UNPIVOT
                        (
                           columns
                           FOR value IN('+ @cols + ')
                        ) AS u
                    ) 
                    SELECT 
                      region, 
                      lob,
                      columns,
                      CAST(CASE WHEN value LIKE ''GWP%'' THEN REPLACE(value,''GWP '', '''')
                           WHEN value LIKE ''LR%'' THEN REPLACE(value,''LR '', '''')
                      END AS INT) AS Year,
                      CASE WHEN value LIKE ''GWP%'' THEN ''GWP''
                           WHEN value LIKE ''LR%'' THEN ''LR''
                      END AS Metrics
                    FROM Unpivoted';


    EXECUTE(@query);



  1. Database
  2.   
  3. Mysql
  4.   
  5. Oracle
  6.   
  7. Sqlserver
  8.   
  9. PostgreSQL
  10.   
  11. Access
  12.   
  13. SQLite
  14.   
  15. MariaDB
  1. समान आईडी वाली पंक्तियों वाली तालिका से कॉलम का उपयोग करके स्ट्रिंग मान बनाने का सबसे अच्छा तरीका कौन सा है?

  2. SQL सर्वर - जटिल गतिशील पिवट कॉलम

  3. यूडीएफ बनाम प्रत्यक्ष एसक्यूएल प्रदर्शन

  4. परिणाम के रूप में पूर्ण दिनांक-समय मान के साथ SQL सर्वर में प्रति घंटे पंक्तियों की गणना करें

  5. SQL सर्वर में फ़ंक्शन-आधारित अनुक्रमणिका