根据日期范围动态生成列

时间:2014-06-24 03:28:24

标签: sql sql-server

我有表格指标数据

Metric ID         Metric Date             Metric Result       Metric Calculation Color
--------------------------------------------------------------------------------------
001              2004-04-01                 1                   GREEN
002              2004-04-01                 0                   RED
001              2004-05-01                 1                   GREEN
002              2004-05-01                 5                   YELLOW
003              2004-05-01                 2                   GREEN

我希望结果集像

Metric ID        April Result           April Calc Color    May Result   May Calc Color
---------------------------------------------------------------------------------------
001               1                       GREEN                1          RED
002               0                       RED                  5          YELLOW
003                                                            2          GREEN

我使用了数据透视表概念,但它给了我重复的结果,如

Metric ID        April Result           April Calc Color    May Result   May Calc Color
---------------------------------------------------------------------------------------
001               1                       GREEN                NULL       NULL
001               NULL                    NULL                 1          RED
002               0                       RED                  NULL       NULL
002               NULL                    NULL                 5          YELLOW
003                                                            2          GREEN

这是我使用的查询

;With CTE AS
( 
SELECT * FROM ( SELECT C.METRIC_ID,RESULT,COLOR FROM METRICDATA ) Q PIVOT (MAX(RESULT) FOR [RESULT] IN ([April],[May]) )Pv ) PIVOT (MAX(COLOR) FOR [RESULT] IN ([April],[May]) )Pv1 )

应根据查询提供的日期限制生成度量标准结果和计算颜色列。

提前致谢。

2 个答案:

答案 0 :(得分:0)

尝试使用此代替枢轴

Select metricId,
Case when datepart(Metric_Date)=4 then Metric_Result else o end 'April Result',
Case when datepart(Metric_Date)=4 then Metric_Color else NULL end 'April Calc Color',
Case when datepart(Metric_Date)=5 then Metric_Result else o end 'MayResult',
Case when datepart(Metric_Date)=5 then Metric_Color else NULL end 'May Calc Color'
from Metric

答案 1 :(得分:0)

这很有趣。 SQLFiddle不喜欢我的代码(我似乎不太喜欢变量)但这适用于我的本地框。这是要测试的模式:

CREATE TABLE METRICDATA
    ([Metric_ID] varchar(3), [Date] date, [Result] int, [Color] varchar(6))
;

INSERT INTO METRICDATA
    ([Metric_ID], [Date], [Result], [Color])
VALUES
    ('001', '2004-04-01', 1, 'GREEN'),
    ('002', '2004-04-01', 0, 'RED'),
    ('001', '2004-05-01', 1, 'GREEN'),
    ('002', '2004-05-01', 5, 'YELLOW'),
    ('003', '2004-05-01', 2, 'GREEN')
;

这是代码:

DECLARE @StartDate AS DATE,
        @EndDate AS DATE,
        @SQL VARCHAR(MAX);

SET @StartDate = '20040401';
SET @EndDate = '20040501';

WITH cteWithMonths
AS
(
    SELECT      Metric_ID,
                DATENAME(MONTH, Date) AS MonthName,
                DATEPART(M, Date) AS Month,
                MAX(DATEPART(M, Date)) OVER () AS MaxMonth,
                Color
    FROM
                METRICDATA
    WHERE
                Date BETWEEN @StartDate AND @EndDate
    GROUP BY
                Metric_ID,
                DATENAME(MONTH, Date),
                DATEPART(M, Date),
                Color
),
cteSQLFieldList
AS
(
    SELECT      0 AS LineNum, 'SELECT DISTINCT m.Metric_ID,' AS SQL
    UNION ALL
    SELECT      DISTINCT
                MONTH,
                CASE 
                    WHEN Month < MaxMonth THEN MonthName + '.' + MonthName + '_Result, ' + MonthName + '.' + MonthName + '_Calc_Color,'
                    ELSE MonthName + '.' + MonthName + '_Result, ' + MonthName + '.' + MonthName + '_Calc_Color'
                END
    FROM        cteWithMonths
    UNION ALL
    SELECT      13,
                'FROM METRICDATA m'
),
cteSQLJoinList
AS
(
    SELECT      DISTINCT
                MONTH + 13 AS LineNum,
                'LEFT JOIN (SELECT Metric_ID, SUM(RESULT) AS ' + MonthName + '_Result, Color AS ' + MonthName + '_Calc_Color FROM METRICDATA WHERE DATENAME(MONTH, Date) = ''' + MonthName + ''' GROUP BY Metric_ID, Color) ' + MonthName +' ON m.Metric_ID = ' + MonthName + '.Metric_ID' AS SQL
    FROM        cteWithMonths
),
cteSQLOrderByList
AS
(
    SELECT      26 AS LineNum,
                'ORDER BY m.Metric_ID' AS SQL
),
cteSQL_ALL
AS
(
    SELECT      *
    FROM        cteSQLFieldList
    UNION
    SELECT      *
    FROM        cteSQLJoinList
    UNION
    SELECT      *
    FROM        cteSQLOrderByList
)

SELECT      @SQL = COALESCE(@SQL + ' ', '') + SQL
FROM        cteSQL_ALL
ORDER BY    LineNum;

EXEC(@SQL);

说实话,我不想玩你的PIVOT解决方案。看起来动态构建很复杂。我选择在dervied表中为每个Metric_ID进行聚合,然后将所有这些聚合在一起。我生成必要的动态SQL然后执行它。