SQL在行跨越上选择列跨区数据

时间:2015-01-23 08:08:54

标签: sql sql-server

我有下表:

REPORT_MONTH    FORECAST_1  FORECAST_2  FORECAST_3  FORECAST_4  FORECAST_5  FORECAST_6  FORECAST_7  FORECAST_8  FORECAST_9  FORECAST_10 FORECAST_11 FORECAST_12
201501            23            23        14         51            25          27          28            29         36          35           12          42
201502            24            25        26         12            4           25          26            7           8          21           4           24

以上记录了基于起始月份的未来12个月的销售预测(EX:如果报告月份为201501,则Forecast_2指的是2015年3月份的销售预测)

鉴于此架构,我想选择以下数据:

REPORT_MONTH    FORECAST_MONTH  FORECAST_VALUE
201501             201502             23
201501             201503             23
201501             201504             14
201501             201505             51
201501             201506             25
201501             201507             27
201501             201508             28
201501             201509             29
201501             201510             36
201501             201511             35
201501             201512             12
201501             201601             42
201502             201503             24
201502             201504             25
201502             201505             26
201502             201506             12
201502             201507             4
201502             201508             25
201502             201509             26
201502             201510             7
201502             201511             8
201502             201512             21
201502             201601             4
201502             201602             24

除非必须将varchar日期转换为datetime,否则这是否有可能?

2 个答案:

答案 0 :(得分:1)

不是最好的解决方案,但您可以使用一组union s:

select report_month
,      substring(convert(varchar, dateadd(month, 1 /*month nr*/, convert(date, report_month + '01', 112)), 112), 1, 6) forcast_month
,      forecast_01 forecast_value
from   tableName
union
all
select report_month
,      substring(convert(varchar, dateadd(month, 2 /*month nr*/, convert(date, report_month + '01', 112)), 112), 1, 6) forcast_month
,      forecast_02 forecast_value
from   tableName

Etc等。

答案 1 :(得分:0)

您可以使用UNPIVOT获取更多succint查询:

SELECT REPORT_MONTH, FORECAST_VALUE, 
       ROW_NUMBER() OVER (PARTITION BY REPORT_MONTH ORDER BY FORECAST) AS rn
FROM 
   (SELECT REPORT_MONTH, FORECAST_1, FORECAST_2, FORECAST_3, ...etc
    FROM #FORECASTS) p
UNPIVOT
   (FORECAST_VALUE FOR FORECAST IN (FORECAST_1, FORECAST_2, FORECAST_3, ...etc))AS unpvt;

上述查询产生的输出类似于:

REPORT_MONTH    FORECAST_VALUE  rn
----------------------------------
201501          23              1
201501          23              2
201501          14              3
....
201502          24              1
201502          25              2 
201502          26              3
.....

您现在可以将上述查询包装在另一个查询中并使用rnREPORT_MONTH来计算FORECAST_MONTH

SELECT REPORT_MONTH, 
       DATEADD(MONTH, rn, CONVERT(DATE, CONCAT(REPORT_MONTH, '01'))) AS FORECAST_MONTH, 
       FORECAST_VALUE
FROM (
   SELECT REPORT_MONTH, FORECAST_VALUE, 
          ROW_NUMBER() OVER (PARTITION BY REPORT_MONTH ORDER BY FORECAST) AS rn
   FROM 
      (SELECT REPORT_MONTH, FORECAST_1, FORECAST_2, FORECAST_3, ...etc
       FROM #FORECASTS) p
   UNPIVOT
      (FORECAST_VALUE FOR FORECAST IN (FORECAST_1, FORECAST_2, FORECAST_3, ...etc ))AS unpvt
) t

输出:

REPORT_MONTH    FORECAST_MONTH  FORECAST_VALUE
----------------------------------------------
201501          2015-02-01      23
201501          2015-03-01      23
201501          2015-04-01      14
... etc
201502          2015-03-01      24
201502          2015-04-01      25
201502          2015-05-01      26
... etc