简体   繁体   中英

Pivoting rows into columns in SQL Server 2008 R2

I have a table like this

ProductID  ValidFrom   ValidTo     Count
----------------------------------------
1           10/1/2015  20/12/2015    100
1           1/4/2014  31/12/2014     200
1           2/2/2013  20/9/2013      300

And I need a pivoted result like this

ProductID      CurrentYearValidity      CurrentYearCount   PreviousYearValidity   PreviousYearCount   PreviousTowYearsValidity  PreviousTwoYearCount
1           10/1/2015 to 20/12/2015        100            1/4/2014 to 31/12/2014       200                9/5/2014 to 20/9/2014     300

If the current date falls between a particular ValidFrom and ValidTo then, it should be displayed under column CurrentYearValidity. If today is 26 March 2015 then if 26 March 2014 falls between a particular ValidFrom and ValidTo, then it should be displayed under column PreviousYearValidity. Respective Count also should be displayed under appropriate columns.

I tried with case statement like this,

select 
    ProductID,
    [CurrentValidity] = case 
                  when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
                    then (CONVERT(varchar(30),ValidFrom,110)+' to '+CONVERT(varchar(30),ValidTo,110))
                  else NULL
                END,
     [CurrentYearCount] = case 
                  when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
                    then Count
                  else NULL
                END,
     [PreviousYearValidity] = case 
                  when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
                    then (CONVERT(varchar(30),ValidFrom,110)+' to '+CONVERT(varchar(30),ValidTo,110))
                  else NULL
                END,
     [PreviousYearCount] = case 
                  when CONVERT(datetime,CONVERT(char(10),GETDATE(),101)) BETWEEN CONVERT(datetime,CONVERT(char(10),ValidFrom,101)) AND CONVERT(datetime,CONVERT(char(10),ValidTo,101))
                    then Count
                  else NULL
                END

But the result is displayed as

ProductID      CurrentYearValidity      CurrentYearCount   PreviousYearValidity   PreviousYearCount   PreviousTowYearsValidity  PreviousTwoYearCount
1           10/1/2015 to 20/12/2015        100          
1              NULL                         NULL         1/4/2014 to 31/12/2014       200                
1              NULL                         NULL             NULL                       NULL                   2/2/2013 to 20/9/2013        300

I want the result in a view.

Please Help.

Edit: If the table has only values

 ProductID  ValidFrom   ValidTo     Count
----------------------------------------
 1           1/4/2014  31/12/2014     200
 1           2/2/2013  20/9/2013      300

then the result should be displayed as

 ProductID      CurrentYearValidity      CurrentYearCount   PreviousYearValidity   PreviousYearCount   PreviousTowYearsValidity  PreviousTwoYearCount
1           NULL        NULL            1/4/2014 to 31/12/2014       200                2/2/2013 to 20/9/2013     300

@Giorgi Nakeuri In this case, your query fails. For your query, the result is,

 ProductID      CurrentYearValidity      CurrentYearCount   PreviousYearValidity   PreviousYearCount   PreviousTowYearsValidity  PreviousTwoYearCount
1                1/4/2014 to 31/12/2014       200            2/2/2013 to 20/9/2013     300               NULL                   NULL

Try:

DECLARE @t TABLE
    (
      ProductID INT ,
      ValidFrom DATE ,
      ValidTo DATE ,
      Count INT
    )
INSERT  INTO @t
VALUES  ( 1, '20150110', '20151220', 100 ),
        ( 1, '20140104', '20141231', 200 ),
        ( 1, '20130202', '20130920', 300 );
WITH    cte1
          AS ( SELECT   ProductID ,
                        CAST(ValidFrom AS NVARCHAR(10)) AS ValidFrom ,
                        ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
               FROM     @t
             ),
        cte2
          AS ( SELECT   ProductID ,
                        CAST(ValidTo AS NVARCHAR(10)) AS ValidTo ,
                        ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
               FROM     @t
             ),
        cte3
          AS ( SELECT   ProductID ,
                        Count ,
                        ROW_NUMBER() OVER ( PARTITION BY ProductID ORDER BY ValidFrom DESC ) AS rn
               FROM     @t
             )
    SELECT  p1.ProductID ,
            p1.[1] + ' to ' + p2.[1] AS CurrentYearValidity ,
            p3.[1] AS CurrentYearCount ,
            p1.[2] + ' to ' + p2.[2] AS PreviousYearValidity ,
            p3.[2] AS PreviousYearCount ,
            p1.[3] + ' to ' + p2.[3] AS PreviousTowYearsValidity ,
            p3.[3] AS PreviousTwoYearCount
    FROM    ( SELECT    *
              FROM      cte1 PIVOT( MAX(ValidFrom) FOR rn IN ( [1], [2], [3] ) ) p
            ) p1
            JOIN ( SELECT   *
                   FROM     cte2 PIVOT( MAX(ValidTo) FOR rn IN ( [1], [2], [3] ) ) p
                 ) p2 ON p2.ProductID = p1.ProductID
            JOIN ( SELECT   *
                   FROM     cte3 PIVOT( MAX(Count) FOR rn IN ( [1], [2], [3] ) ) p
                 ) p3 ON p3.ProductID = p2.ProductID

Output:

ProductID   CurrentYearValidity         CurrentYearCount    PreviousYearValidity        PreviousYearCount   PreviousTowYearsValidity    PreviousTwoYearCount
1           2015-01-10 to 2015-12-20    100                 2014-01-04 to 2014-12-31    200                 2013-02-02 to 2013-09-20    300

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM