从行中的日期派生列名称并在sql中显示每月数据

时间:2016-07-19 06:32:00

标签: sql sql-server

我有一张如下表:

CREATE table #yourtable
(
    [Id] int, 
    [ColumnName] varchar(13), 
    Val1 float, 
    Val2 float, 
    StartDate datetime, 
    EndDate datetime
);

INSERT INTO #yourtable
    ([Id], [ColumnName],Val1,Val2,StartDate,EndDate)
VALUES
    (1,'ABC12',1000,900,'2016-01-01 00:00:00','2016-01-31 23:59:59'),
    (2,'ABC12',1100,900,'2016-02-01 00:00:00','2016-02-29 23:59:59'),
    (3,'CDE34',1000,800,'2016-01-01 00:00:00','2016-01-31 23:59:59'),
    (4,'EFG45',1000,700,'2016-03-01 00:00:00','2016-03-31 23:59:59'),
    (5,'FGH56',1000,1001,'2016-02-01 00:00:00','2016-02-29 23:59:59');

我试图获得如下的月度隔离数据:

Column Name Jan      Feb      Mar
    ABC12   1000     1100     null
    ABC12   900      900      null
    CDE34   1000     null     null
    CDE34   800      null     null
    EFG45   null     null     1000
    EFG45   null     null     700
    FGH56   null     1000     null
    FGH56   null     1001     null

我对sql相对较新。 提前致谢

2 个答案:

答案 0 :(得分:1)

试试这个..

SELECT  * FROM (SELECT  [ColumnName],
            SUM(Val1) AS _Val, 
            CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(StartDate), - 1))) MonthCol
            FROM #yourtable WHERE YEAR(StartDate) = 2016
            GROUP BY  StartDate,[ColumnName]) AS TP
     PIVOT (SUM(_Val) FOR MonthCol IN ([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) AS PVTTable
UNION
SELECT  * FROM (SELECT  [ColumnName],
            SUM(Val2) AS _Val, 
            CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(EndDate), - 1))) MonthCol
            FROM #yourtable WHERE YEAR(EndDate) = 2016
            GROUP BY  EndDate,[ColumnName]) AS TP
     PIVOT (SUM(_Val) FOR MonthCol IN ([Jan], [Feb], [Mar], [Apr], [May], [Jun], [Jul], [Aug], [Sep], [Oct], [Nov], [Dec])) AS PVTTable

用于动态查询

    DECLARE @MaxMonth DATE = GETDATE();
    DECLARE @YearData NVARCHAR(4) = CAST(YEAR(@MaxMonth) AS NVARCHAR(4))
    DECLARE @END_MM INT = MONTH(@MaxMonth) --End of Month
    DECLARE @START_MM INT = 1 --Start Month of Year Data

    DECLARE @TB_DATE AS TABLE
    (
        ID INT IDENTITY(1,1),
        MONTH_LIST VARCHAR(12)
    )
    WHILE @START_MM <= @END_MM
    BEGIN
        INSERT INTO @TB_DATE (MONTH_LIST) VALUES ('['+CONVERT(VARCHAR(3),DATENAME(MONTH, DATEADD(MONTH, @START_MM-1, CAST(@END_MM AS datetime))))+']')
        SET @START_MM=@START_MM+1
    END

    DECLARE @MM_LIST NVARCHAR(MAX) = (SELECT STUFF((SELECT ',' + MONTH_LIST 
                        FROM @TB_DATE ORDER BY ID DESC
                        FOR XML PATH('')) ,1,1,'') AS Txt)

    DECLARE @DynamicPivot AS NVARCHAR(MAX)
    SET @DynamicPivot = N' SELECT  * FROM (SELECT  [ColumnName],
            SUM(Val1) AS _Val, 
            CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(StartDate), - 1))) MonthCol
            FROM #yourtable WHERE YEAR(StartDate) = '+@YearData+'
            GROUP BY  StartDate,[ColumnName]) AS TP
     PIVOT (SUM(_Val) FOR MonthCol IN ('+@MM_LIST+')) AS PVTTable
     UNION
     SELECT  * FROM (SELECT  [ColumnName],
            SUM(Val2) AS _Val, 
            CONVERT(VARCHAR(3), DATENAME(MONTH, DATEADD(MONTH, MONTH(EndDate), - 1))) MonthCol
            FROM #yourtable WHERE YEAR(EndDate) = '+@YearData+'
            GROUP BY  EndDate,[ColumnName]) AS TP
     PIVOT (SUM(_Val) FOR MonthCol IN ('+@MM_LIST+')) AS PVTTable';

 EXEC sp_executesql @DynamicPivot

答案 1 :(得分:1)

使用pivoting

SELECT  ColumnName,
        MAX([Jan]) as [Jan],
        MAX([Feb]) as [Feb],
        MAX([Mar]) as [Mar],
        MAX([Apr]) as [Apr],
        MAX([May]) as [May],
        MAX([Jun]) as [Jun],
        MAX([Jul]) as [Jul],
        MAX([Aug]) as [Aug]
FROM (
    SELECT  Id,
            ColumnName,
            LEFT(DATENAME(MONTH,StartDate),3) as M,
            [Vals],
            [Column]
    FROM
    (SELECT *
    FROM #yourtable) y
    UNPIVOT (
         [Column] FOR Vals IN ([Val1],[Val2])
    )as unpvt
    ) as s
PIVOT (
    MAX([Column]) FOR M IN ([Jan],[Feb],[Mar],[Apr],[May],[Jun],[Jul],[Aug])
) as pvt
GROUP BY ColumnName,Vals
ORDER BY ColumnName

输出:

ColumnName  Jan     Feb     Mar
ABC12       1000    1100    NULL
ABC12       900     900     NULL
CDE34       1000    NULL    NULL
CDE34       800     NULL    NULL
EFG45       NULL    NULL    1000
EFG45       NULL    NULL    700
FGH56       NULL    1000    NULL
FGH56       NULL    1001    NULL

使用UNPIVOT,我们得到了这个表结构:

Id  ColumnName  M   Vals    Column
1   ABC12       Jan Val1    1000
1   ABC12       Jan Val2    900
2   ABC12       Feb Val1    1100
2   ABC12       Feb Val2    900
3   CDE34       Jan Val1    1000
3   CDE34       Jan Val2    800
4   EFG45       Mar Val1    1000
4   EFG45       Mar Val2    700
5   FGH56       Feb Val1    1000
5   FGH56       Feb Val2    1001

因此,所有Vals都在一列中,然后我们使用PIVOTGROUP BYORDER BY的帮助下获得所需的结果。

如果有许多Vals更好地使用动态SQL。