Sqlserver
 sql >> база данни >  >> RDS >> Sqlserver

Трансформирайте вертикален резултат в хоризонтален режим (T-SQL)

Както беше казано, това всъщност не е възможно, най-близкото, което можете да получите, е:

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 Fiddle

Моля, имайте предвид, че все още не препоръчвам тази техника и смятам, че SQL трябва да бъде оставен да съхранява/извлича данни и презентационния слой да ги форматира




  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 Server 2008 Backup Compression Standard Edition

  2. SQL SERVER 2008 ПОЛУЧАВА ПОСЛЕДНО ВМЪКНАТИ СТОЙНОСТИ

  3. 3 начина да получите първия ден от месеца в SQL Server

  4. Как да пуснете списък с таблици на SQL Server, като игнорирате ограниченията?

  5. scope_identity срещу ident_current