2013-08-01 40 views
0

我将不胜感激。我有如下数据的SQL Server数据库称为info_source表:SQL Server将行移动到列

Date  StatCode Value_1 Value_2 Remarks 
---------- -------- ------- ------- ------- 
2012-11-01 SRC_1  18775  648  Normal 
2012-11-01 SRC_2  308218 249  Normal 
2012-11-01 SRC_3  0   0  Off 
2012-11-02 SRC_4  123181 523  Normal 
2012-11-02 SRC_5  189231 247  Normal 

我会用一个加盟站的名称替换statCode领域。我想转换成列在报表中类似的东西来这行:

Date  StatName Value_1 Value_2 Remarks StatName Value_1 Value_2 Remarks 
---------- ---------- ------- ------- ------- ---------- ------- ------- ------- 
2012-11-01 (SRC_1)ABC 18775 648  Normal (SRC_2)DEF 308218 249  Normal 
2012-11-02 (SRC_4)JKL 123181 523  Normal (SRC_5)MNO 189231 247  Normal 

我要创建一个视图,但未能解决问题。比我研究和发现关于数据透视表的一些信息,但我无法抓住如何编写一个我想要的查询。

编辑

这是我到目前为止已经试过:

SELECT * FROM (
SELECT date AS [date], statCode AS [station], value_1 AS [val1], 
value_2 AS [val2], remarks AS [remks] FROM info_source 
) AS query1 
+2

欢迎使用堆栈溢出。即使你尝试过的东西不起作用,我们也很欣赏看到这些代码。这证明你已经做了一个尝试,并阻止你获得你已经尝试过的答案。 –

+0

SRC_3行发生了什么? –

+0

@AaronBertrand我删除了那一行。 – tanner

回答

2

为了你得到的结果,我的建议是使用row_number()窗函数,UNPIVOT你列statcodevalue_1,value_2remarks,最后应用PIVOT功能。

第一步是查询您的数据并应用row_number()函数。由于您有在列要多行数据,您需要一种方法来保持相互关联的值:

select date, value_1, value_2, statcode, remarks, 
    row_number() over(partition by date 
        order by statcode) seq 
from yourtable; 

Demo。这将为表格中的每个日期的每行分配一个连续编号。我使用order by statcode,但如果您有另一个值来保持项目的特定顺序,那么您将使用该列。

一旦您指定的行数,那么你将在列statcodevalue_1value_2remarks unpivot的数据。您可以使用UNPIVOT函数,也可以使用CROSS APPLY将多列转换为多行数据。当你改变你将留下3列,日期,上一列的值,然后将在PIVOT使用新列名的数据:

select date, 
    col = col+'_'+cast(seq as varchar(10)), 
    value 
from 
(
    select date, value_1, value_2, statcode, remarks, 
    row_number() over(partition by date 
         order by statcode) seq 
    from yourtable 
) src 
cross apply 
(
    select 'statcode', statcode union all 
    select 'value_1', cast(value_1 as varchar(10)) union all 
    select 'value_2', cast(value_2 as varchar(10)) union all 
    select 'remarks', remarks 
) c (col, value); 

Demo。这会给你的数据格式:

|       DATE |  COL | VALUE | 
--------------------------------------------------------- 
| November, 01 2012 00:00:00+0000 | statcode_1 | SRC_1 | 
| November, 01 2012 00:00:00+0000 | value_1_1 | 18775 | 
| November, 01 2012 00:00:00+0000 | value_2_1 | 648 | 
| November, 01 2012 00:00:00+0000 | remarks_1 | Normal | 
| November, 01 2012 00:00:00+0000 | statcode_2 | SRC_2 | 
| November, 01 2012 00:00:00+0000 | value_1_2 | 308218 | 

最后将应用旋转功能的项目在新的专栏中,我叫col

select date, 
    statcode_1, value_1_1, value_2_1, remarks_1, 
    statcode_2, value_1_2, value_2_2, remarks_2, 
    statcode_3, value_1_3, value_2_3, remarks_3 
from 
(
    select date, 
    col = col+'_'+cast(seq as varchar(10)), 
    value 
    from 
    (
    select date, value_1, value_2, statcode, remarks, 
     row_number() over(partition by date 
         order by statcode) seq 
    from yourtable 
) src 
    cross apply 
    (
    select 'statcode', statcode union all 
    select 'value_1', cast(value_1 as varchar(10)) union all 
    select 'value_2', cast(value_2 as varchar(10)) union all 
    select 'remarks', remarks 
) c (col, value) 
) d 
pivot 
(
    max(value) 
    for col in (statcode_1, value_1_1, value_2_1, remarks_1, 
       statcode_2, value_1_2, value_2_2, remarks_2, 
       statcode_3, value_1_3, value_2_3, remarks_3) 
) piv; 

SQL Fiddle with Demo。现在上面的代码会为你工作,你有一个已知的值,但如果你有未知的值,那么你将需要使用动态SQL。动态SQL代码:

DECLARE @cols AS NVARCHAR(MAX), 
    @query AS NVARCHAR(MAX) 

select @cols = STUFF((SELECT ',' + QUOTENAME(col+'_'+cast(seq as varchar(10))) 
        from 
        (
         select row_number() over(partition by date 
               order by statcode) seq 
         from yourtable 
        ) t 
        cross apply 
        (
         select 'statcode', 1 union all 
         select 'value_1', 2 union all 
         select 'value_2', 3 union all 
         select 'remarks', 4 
        ) c (col, so) 
        group by col, seq, so 
        order by seq, so 
      FOR XML PATH(''), TYPE 
      ).value('.', 'NVARCHAR(MAX)') 
     ,1,1,'') 

set @query = 'SELECT date,' + @cols + ' 
      from 
      (
       select date, 
       col = col+''_''+cast(seq as varchar(10)), 
       value 
       from 
       (
       select date, value_1, value_2, statcode, remarks, 
        row_number() over(partition by date 
            order by statcode) seq 
       from yourtable 
      ) src 
       cross apply 
       (
       select ''statcode'', statcode union all 
       select ''value_1'', cast(value_1 as varchar(10)) union all 
       select ''value_2'', cast(value_2 as varchar(10)) union all 
       select ''remarks'', remarks 
      ) c (col, value) 
      ) x 
      pivot 
      (
       max(value) 
       for col in (' + @cols + ') 
      ) p ' 

execute sp_executesql @query; 

SQL Fiddle with Demo。两种版本都会给出结果:

|       DATE | STATCODE_1 | VALUE_1_1 | VALUE_2_1 | REMARKS_1 | STATCODE_2 | VALUE_1_2 | VALUE_2_2 | REMARKS_2 | STATCODE_3 | VALUE_1_3 | VALUE_2_3 | REMARKS_3 | 
-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- 
| November, 01 2012 00:00:00+0000 |  SRC_1 |  18775 |  648 | Normal |  SRC_2 | 308218 |  249 | Normal |  SRC_3 |   0 |   0 |  Off | 
| November, 02 2012 00:00:00+0000 |  SRC_4 | 123181 |  523 | Normal |  SRC_5 | 189231 |  247 | Normal |  (null) | (null) | (null) | (null) | 
+0

感谢您的帮助。我会试一试。 – tanner