Convert vertical result to horizontal mode (T-SQL)

Here is an example of data:

CalculationDate PLResult
2014-01-02        100         
2014-01-03        200         
2014-02-03        300         
2014-02-04        400         
2014-02-27        500         

Here is the expected result (in logical format):

January                                  February                                 
CalculationDate PLResult CalculationDate PLResult  
2014-01-02        100          2014-02-03        300          
2014-01-03        200          2014-02-04        400          
                                           2014-02-27        500          

Here is the expected result (using a T-SQL query):

Jan-CalculationDate Jan-PLResult Feb-CalculationDate Feb-PLResult  
2014-01-02               100                 2014-02-03               300                  
2014-01-03               200                 2014-02-04               400                  
                                                         2014-02-27               500                  

Purpose:

  • Classify the result according to the month. In the above example, the January results are placed in the January breakdown.
  • The number of months can be dynamic. In the above example, this only shows January and February, because there are only 2-month results.
  • The result will be displayed through Excel. In fact, I can query several query tables to aggregate the result in different months, but if you can return the whole result through one query, then it will be easier to maintain and debug.

Here are the scripts to populate the sample data:

CREATE TABLE #PLResultPerDay ( CalculationDate DATETIME, PLResult DECIMAL(18,8) )
INSERT INTO #PLResultPerDay ( CalculationDate, PLResult ) VALUES ('2014-01-02' , 100 )
INSERT INTO #PLResultPerDay ( CalculationDate, PLResult ) VALUES ('2014-01-03' , 200 )
INSERT INTO #PLResultPerDay ( CalculationDate, PLResult ) VALUES ('2014-02-03' , 300 )
INSERT INTO #PLResultPerDay ( CalculationDate, PLResult ) VALUES ('2014-02-04' , 400 )

So far I am trying to build a query:

SELECT 
    CalculationDate, [January], CalculationDate, [February]
FROM 
(
    SELECT CalculationDate, PLResult, DATENAME(MONTH, CalculationDate) AS [MTH]
    FROM #PLResultPerDay
) x
PIVOT
( 
    MIN(PLResult)
    FOR [MTH] IN ([January], [February])
) p
+4
1

, , :

January2014CalculationDate | January2014PLResult | February2014CalculationDate | February2014PLResult
---------------------------+---------------------+-----------------------------+------------------
    2014-01-02             |       100           |       2014-02-03            |       300
    2014-01-03             |       200           |       2014-02-04            |       400
    NULL                   |       NULL          |       2014-02-27            |       500

, - , sql. , :

SELECT  CalculationDate,
        PLResult,
        CalculationMonth,
        DenseRank = DENSE_RANK() OVER(PARTITION BY CalculationMonth ORDER BY CalculationDate)
FROM    (   SELECT  CalculationDate,
                    PLResult,
                    CalculationMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, CalculationDate), 0)
            FROM    #PLResultPerDay
        ) pl;

:

CalculationDate PLResult    CalculationMonth    DenseRank
2014-01-02      100         2014-01-01          1
2014-01-03      200         2014-01-01          2
2014-02-03      300         2014-02-01          1
2014-02-04      400         2014-02-01          2
2014-02-27      500         2014-02-01          3

:

WITH Data AS
(   SELECT  CalculationDate,
            PLResult,
            CalculationMonth,
            DenseRank = DENSE_RANK() OVER(PARTITION BY CalculationMonth ORDER BY CalculationDate)
    FROM    (   SELECT  CalculationDate,
                        PLResult,
                        CalculationMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, CalculationDate), 0)
                FROM    #PLResultPerDay
            ) pl
)
SELECT  Jan2014CalcDate = MIN(CASE WHEN CalculationMonth = '20140101' THEN CalculationDate END),
        Jan2014Result = SUM(CASE WHEN CalculationMonth = '20140101' THEN PLResult END),
        Feb2014CalcDate = MIN(CASE WHEN CalculationMonth = '20140201' THEN CalculationDate END),
        Feb2014Result = SUM(CASE WHEN CalculationMonth = '20140201' THEN PLResult END)
FROM    Data
GROUP BY DenseRank
ORDER BY DenseRank;

:

Jan2014CalcDate Jan2014Result   Feb2014CalcDate Feb2014Result
2014-01-02      100             2014-02-03      300
2014-01-03      200             2014-02-04      400
NULL            NULL            2014-02-27      500

, , SP_EXECUTESQL :

DECLARE @SQL NVARCHAR(MAX) = '';

WITH Months AS
(   SELECT  M,
            ColName = DATENAME(MONTH, M) + DATENAME(YEAR, M),
            CharFormat = CONVERT(VARCHAR(8), M, 112)
    FROM    (   SELECT  DISTINCT M = DATEADD(MONTH, DATEDIFF(MONTH, 0, CalculationDate), 0)
                FROM    #PLResultPerDay
            ) m
)
SELECT  @SQL = 'WITH Data AS
                (   SELECT  CalculationDate,
                            PLResult,
                            CalculationMonth,
                            DenseRank = DENSE_RANK() OVER(PARTITION BY CalculationMonth ORDER BY CalculationDate)
                    FROM    (   SELECT  CalculationDate,
                                        PLResult,
                                        CalculationMonth = DATEADD(MONTH, DATEDIFF(MONTH, 0, CalculationDate), 0)
                                FROM    #PLResultPerDay
                            ) pl
                )
                SELECT  ' + 
                STUFF(( SELECT  ', ' + ColName + 'CalculationDate = MIN(CASE WHEN CalculationMonth = ''' + CharFormat + ''' THEN CalculationDate END), ' + 
                                ColName + 'PLResult = SUM(CASE WHEN CalculationMonth = ''' + CharFormat + ''' THEN PLResult END)'
                        FROM    Months
                        ORDER BY M
                        FOR XML PATH(''), TYPE
                    ).value('.', 'NVARCHAR(MAX)'), 1, 2, '') + 
                'FROM   Data
                GROUP BY DenseRank
                ORDER BY DenseRank;';

EXECUTE SP_EXECUTESQL @SQL;

SQL

, , SQL / ,

+5

All Articles