T-SQL में PIVOT फ़ंक्शन को समझना


82

मैं SQL के लिए बहुत नया हूँ।

मेरे पास एक तालिका है:

ID | TeamID | UserID | ElementID | PhaseID | Effort
-----------------------------------------------------
1  |   1    |  1      |   3       |  5     |   6.74
2  |   1    |  1      |   3       |  6     |   8.25
3  |   1    |  1      |   4       |  1     |   2.23
4  |   1    |  1      |   4       |  5     |   6.8
5  |   1    |  1      |   4       |  6     |   1.5

और मुझे कहा गया कि इस तरह से डेटा प्राप्त करें

ElementID | PhaseID1 | PhaseID5 | PhaseID6
--------------------------------------------
    3     |   NULL   |   6.74   |   8.25
    4     |   2.23   |   6.8    |   1.5

मैं समझता हूं कि मुझे PIVOT फ़ंक्शन का उपयोग करने की आवश्यकता है। लेकिन इसे स्पष्ट रूप से नहीं समझ सकते। यह बहुत मददगार होगा अगर कोई इसे उपरोक्त मामले में समझा सकता है। (या यदि कोई विकल्प हो तो)

जवाबों:


109

एक PIVOTडेटा को एक कॉलम से कई कॉलम में घुमाने के लिए उपयोग किया जाता है।

आपके उदाहरण के लिए यहां एक स्थिर धुरी है जिसका अर्थ है कि आप उन स्तंभों को कठिन कोड देते हैं जिन्हें आप घुमाना चाहते हैं:

create table temp
(
  id int,
  teamid int,
  userid int,
  elementid int,
  phaseid int,
  effort decimal(10, 5)
)

insert into temp values (1,1,1,3,5,6.74)
insert into temp values (2,1,1,3,6,8.25)
insert into temp values (3,1,1,4,1,2.23)
insert into temp values (4,1,1,4,5,6.8)
insert into temp values (5,1,1,4,6,1.5)

select elementid
  , [1] as phaseid1
  , [5] as phaseid5
  , [6] as phaseid6
from
(
  select elementid, phaseid, effort
  from temp
) x
pivot
(
  max(effort)
  for phaseid in([1], [5], [6])
)p

यहां एक कार्यशील संस्करण के साथ एक SQL डेमो है

यह एक गतिशील PIVOT के माध्यम से भी किया जा सकता है जहाँ आप गतिशील रूप से स्तंभों की सूची बनाते हैं और PIVOT करते हैं।

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

select @cols = STUFF((SELECT distinct ',' + QUOTENAME(c.phaseid) 
            FROM temp c
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')

set @query = 'SELECT elementid, ' + @cols + ' from 
            (
                select elementid, phaseid, effort
                from temp
           ) x
            pivot 
            (
                 max(effort)
                for phaseid in (' + @cols + ')
            ) p '


execute(@query)

दोनों के लिए परिणाम:

ELEMENTID   PHASEID1    PHASEID5    PHASEID6
3           Null        6.74        8.25
4           2.23        6.8         1.5

1
धन्यवाद मिल गया। केवल मुझे PhaseIDQUOTENAME से पहले हार्ड कोड की आवश्यकता है । सही?
वेब-ई

1
QUOTENAME में आपको यह पहचानना होगा कि आपको किस कॉलम से मान प्राप्त करने की आवश्यकता है। क्या आप जो पूछ रहे हैं?
तरण

अजीब स्तंभ नाम (रिक्त स्थान, कोष्ठक, आदि) के साथ STUFF समाधान कार्य करने के लिए मुझे क्या करना था SELECT distinct '],[', और बयान के अंत में भी1, 2, '') + ']'
Nat

@ वेब-ई, दुर्भाग्य से हाँ। वर्कअराउंड के रूप में आप अपने एप्लिकेशन में क्वेरी स्ट्रिंग लिख सकते हैं या संग्रहीत कार्यविधि में गतिशील SQL के साथ खेल सकते हैं।
मार्को

7

ये बहुत बुनियादी धुरी उदाहरण हैं जो कृपया उसी से गुजरते हैं।

SQL सर्वर - PIVOT और UNPIVOT टेबल उदाहरण

उत्पाद तालिका के लिए उपरोक्त लिंक से उदाहरण:

SELECT PRODUCT, FRED, KATE
FROM (
SELECT CUST, PRODUCT, QTY
FROM Product) up
 PIVOT (SUM(QTY) FOR CUST IN (FRED, KATE)) AS pvt
ORDER BY PRODUCT

प्रस्तुत करता है:

 PRODUCT FRED  KATE
 --------------------
 BEER     24    12
 MILK      3     1
 SODA   NULL     6
 VEG    NULL     5

इसी तरह के उदाहरण SQL सर्वर में ब्लॉग पोस्ट पिवट टेबल में पाए जा सकते हैं । एक साधारण नमूना


यह भी ध्यान दें, यदि आप स्रोत तालिका से अतिरिक्त सांख्यिक स्तंभ खींचते हैं तो धुरी परिणामों को कई पंक्तियों में तोड़ देती है। उदाहरण SELECT CUST, VEG, SODA FROM (SELECT rand() as x, CUST, PRODUCT, QTY FROM Product) up PIVOT ( SUM(x) FOR PRODUCT IN (VEG, SODA) ) AS pvt ORDER BY CUST GO काम करने के लिए, आपको qtyस्तंभ को स्रोत से हटाना होगा
रहेल हसन

4

Ive यहाँ जोड़ने के लिए कुछ है जिसका किसी ने उल्लेख नहीं किया है।

pivotसमारोह अच्छा काम करता है जब स्रोत 3 स्तंभ हैं: के लिए एक aggregate, के साथ स्तंभों के रूप में प्रसार करने के लिए एक for, और के लिए एक धुरी के रूप एक rowवितरण। उत्पाद उदाहरण में QTY, CUST, PRODUCT

हालाँकि, यदि आपके पास स्रोत में अधिक स्तंभ हैं, तो यह परिणाम को एक पंक्ति के बजाय एकाधिक पंक्तियों में तोड़ देगा, जो कि अतिरिक्त स्तंभ प्रति अद्वितीय मानों के आधार पर Group Byहोगा (जैसा कि एक साधारण क्वेरी में होगा)।

इस उदाहरण को देखें, ive ने स्रोत तालिका में एक टाइमस्टैम्प कॉलम जोड़ा:

यहां छवि विवरण दर्ज करें

अब देखें इसका असर:

SELECT CUST, MILK

FROM Product
-- FROM (SELECT CUST, Product, QTY FROM PRODUCT) p
PIVOT (
    SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt

ORDER BY CUST

यहां छवि विवरण दर्ज करें


इसे ठीक करने के लिए, आप या तो एक उपकेंद्र को एक स्रोत के रूप में खींच सकते हैं जैसा कि सभी ने ऊपर किया है - केवल 3 कॉलम के साथ (यह हमेशा आपके परिदृश्य के लिए काम नहीं करने वाला है, कल्पना करें कि आपको whereटाइमस्टैम्प के लिए एक शर्त लगाने की आवश्यकता है )।

दूसरा उपाय एक उपयोग करना है group byऔर फिर से पिवोटेड कॉलम मानों का योग करना है।

SELECT 
CUST, 
sum(MILK) t_MILK

FROM Product
PIVOT (
    SUM(QTY) FOR PRODUCT IN (MILK)
) AS pvt

GROUP BY CUST
ORDER BY CUST

GO

यहां छवि विवरण दर्ज करें


4

आपके डेटा में से किसी एक कॉलम को पंक्तियों से कॉलम में बदलने के लिए एक पिवट का उपयोग किया जाता है (इसे आमतौर पर फैलाने वाले कॉलम के रूप में जाना जाता है )। आपके द्वारा दिए गए उदाहरण में, इसका मतलब है कि PhaseIDपंक्तियों को स्तंभों के एक समूह में परिवर्तित करना , जहाँ प्रत्येक भिन्न मान के लिए एक स्तंभ है PhaseIDजिसमें इस मामले में - 1, 5 और 6 हो सकते हैं।

इन पिवोटेड मानों को आपके द्वारा दिए गए उदाहरण में कॉलम के माध्यम से समूहीकृतElementID किया जाता है।

आमतौर पर आपको तब एकत्रीकरण के कुछ रूप भी प्रदान करने की आवश्यकता होती है जो आपको फैलाने वाले मूल्य ( PhaseID) और समूहन मूल्य ( ElementID) के चौराहे द्वारा संदर्भित मान प्रदान करता है । हालांकि उदाहरण में दिए गए एकत्रीकरण का उपयोग किया जाना अस्पष्ट है, लेकिन इसमें Effortकॉलम शामिल है ।

एक बार जब यह पिवट किया जाता है, समूहीकरण और प्रसार कॉलम एक खोजने के लिए उपयोग किया जाता है एकत्रीकरण मूल्य । या आपके मामले में, ElementIDऔर PhaseIDXलुकअप Effort

समूहन, प्रसार, एकत्रीकरण शब्दावली का उपयोग करते हुए आप आमतौर पर एक धुरी के लिए उदाहरण वाक्यविन्यास देखेंगे:

WITH PivotData AS
(
    SELECT <grouping column>
        , <spreading column>
        , <aggregation column>
    FROM <source table>
)
SELECT <grouping column>, <distinct spreading values>
FROM PivotData
    PIVOT (<aggregation function>(<aggregation column>)
        FOR <spreading column> IN <distinct spreading values>));

यह एक चित्रमय विवरण देता है कि कैसे समूहन, प्रसार और एकत्रीकरण कॉलम स्रोत से परिवर्तित तालिकाओं में परिवर्तित होता है यदि आगे मदद करता है।


3

संगतता त्रुटि सेट करने के लिए

धुरी फ़ंक्शन का उपयोग करने से पहले इसका उपयोग करें

ALTER DATABASE [dbname] SET COMPATIBILITY_LEVEL = 100  

3
    SELECT <non-pivoted column>,
    [first pivoted column] AS <column name>,
    [second pivoted column] AS <column name>,
    ...
    [last pivoted column] AS <column name>
FROM
    (<SELECT query that produces the data>)
    AS <alias for the source query>
PIVOT
(
    <aggregation function>(<column being aggregated>)
FOR
[<column that contains the values that will become column headers>]
    IN ( [first pivoted column], [second pivoted column],
    ... [last pivoted column])
) AS <alias for the pivot table>
<optional ORDER BY clause>;

USE AdventureWorks2008R2 ;
GO
SELECT DaysToManufacture, AVG(StandardCost) AS AverageCost 
FROM Production.Product
GROUP BY DaysToManufacture;

    DaysToManufacture          AverageCost
0                          5.0885
1                          223.88
2                          359.1082
4                          949.4105

    -- Pivot table with one row and five columns
SELECT 'AverageCost' AS Cost_Sorted_By_Production_Days, 
[0], [1], [2], [3], [4]
FROM
(SELECT DaysToManufacture, StandardCost 
    FROM Production.Product) AS SourceTable
PIVOT
(
AVG(StandardCost)
FOR DaysToManufacture IN ([0], [1], [2], [3], [4])
) AS PivotTable;




Here is the result set.
Cost_Sorted_By_Production_Days    0         1         2           3       4       
AverageCost                       5.0885    223.88    359.1082    NULL    949.4105

1
<SELECT query that produces the data>सिर्फ टेबल क्यों नहीं है?
रहेल हसन
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.