我会感激一些帮助。我在一个名为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
答案 0 :(得分:2)
为了获得结果,我的建议是使用row_number()
窗口功能,取消列statcode
,value_1
,value_2
和{{1}最后应用PIVOT函数。
第一步是查询您的数据并应用remarks
功能。由于列中需要多行数据,因此需要一种方法来保持值彼此关联:
row_number()
见Demo。这将为表中的每个日期为每行分配一个序号。我使用了select date, value_1, value_2, statcode, remarks,
row_number() over(partition by date
order by statcode) seq
from yourtable;
,但是如果您有另一个值来保持特定顺序的项目,那么您将使用该列。
分配行号后,您将取消忽略order by statcode
,statcode
,value_1
和value_2
列中的数据。您可以使用UNPIVOT函数,也可以使用CROSS APPLY将多列转换为多行数据。转换数据时,您将留下3列,日期,上一列的值,然后是将在PIVOT中使用的新列名:
remarks
见Demo。这将为您提供以下格式的数据:
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);
最后,您将PIVOT函数应用于我称为| 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
见SQL Fiddle with Demo。现在上面的代码对你有用了你有一个已知的值,但如果你有未知的值,那么你将需要使用动态SQL。动态SQL代码是:
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。两个版本都会给出结果:
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;