我的输入是包含以下列的视图:
DOCID DATE ROWNUMBER COLUMN1 COLUMN2 COLUMN3 COLUMN4 COLUMN5
ABC000123 2014-04-11 1 approval project name ABC (null) (null)
COLUMN2 的记录需要变为列标题, 值为COLUMN3或COLUMN4。如果COLUMN3为空或为null,则使用COLUMN4。 目前COLUMN5完全为空,因此您可以忽略此列。
问题在于并非每个 DocID 都包含构建标题所需的 COLUMN2 中的所有值。
所以我想用" SELECT DISTINCT column2 AS headings
"在视图的所有条目,然后使用枢轴功能可以让我在某个地方。
但我无法让它发挥作用。
我还需要能够仅选择关于COLUMN2的某个列标题。一旦我有一个可以选择所有列的视图并从中创建一个新视图,这可能会更容易。
看一下示例 Fiddle
我使用的是MSSQL 2012。
我很高兴看到一些示例代码。
谢谢。
答案 0 :(得分:2)
您似乎需要首先忽略列Column3
,Column4
和Column5
以返回非空行,然后转动Column2
项进入专栏。如果您不知道列名,则需要在存储过程中使用动态SQL。
在使用动态sql之前,我首先编写一个静态版本的查询来获得正确的逻辑。由于您使用的是SQL Server 2012,因此可以使用CROSS APPLY和VALUES来取消数据的转出:
select
m.docId,
m.Date,
m.column1,
m.column2,
c.value
from dbo.mappingTest m
cross apply
(
values
('Column3', Column3),
('Column4', Column4),
('Column5', convert(varchar(10), Column5, 120))
) c (Col, Value)
where c.value is not null
见Demo。您的数据现在如下所示:
| DOCID | DATE | COLUMN1 | COLUMN2 | VALUE |
|------------|------------|----------|--------------|---------|
| ABC000123 | 2014-04-11 | approval | project name | ABC |
| ABC000123 | 2014-04-11 | approval | article name | Art 01 |
| ABC000123 | 2014-04-11 | approval | customer | ACME |
| ABC000123 | 2014-04-11 | approval | department | Dept. A |
| ABC000123 | 2014-04-11 | approval | plant | Europe |
| ABC000123 | 2014-04-11 | approval | sop month | 10 |
每个DocID
都有多行,其中您最终需要的值位于单个列的Column2
项目下。现在您可以应用PIVOT功能:
select
DocID,
Date,
Column1,
[project name], [article name], [customer],
[department], [plant], [sop month],
[sop year], [eop month], [eop year], [budget], [savings]
from
(
select
m.docId,
m.Date,
m.column1,
m.column2,
c.value
from dbo.mappingTest m
cross apply
(
values
('Column3', Column3),
('Column4', Column4),
('Column5', convert(varchar(10), Column5, 120))
) c (Col, Value)
where c.value is not null
) d
pivot
(
max(value)
for column2 in ([project name], [article name], [customer],
[department], [plant], [sop month],
[sop year], [eop month], [eop year], [budget], [savings])
) p
见SQL Fiddle with Demo。我已经包含了所有列名,但是在PIVOT IN
内部,您只包含实际需要的值作为新列。
现在,如果您想使用动态SQL,您可以将代码调整为:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX)
select @cols = STUFF((SELECT ',' + QUOTENAME(COLUMN2)
from dbo.mappingTest
group by COLUMN2
order by COLUMN2
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
set @query
= 'SELECT
DocID,
Date,
Column1,' + @cols + '
from
(
select
m.docId,
m.Date,
m.column1,
m.column2,
c.value
from dbo.mappingTest m
cross apply
(
values
(''Column3'', Column3),
(''Column4'', Column4),
(''Column5'', convert(varchar(10), Column5, 120))
) c (Col, Value)
where c.value is not null
) d
pivot
(
min(value)
for column2 in (' + @cols + ')
) p '
exec sp_executesql @query
见SQL Fiddle with Demo。两个版本都会得到以下结果:
| DOCID | DATE | COLUMN1 | ARTICLE NAME | BUDGET | CUSTOMER | DEPARTMENT | EOP MONTH | EOP YEAR | PLANT | PROJECT NAME | SAVINGS | SOP MONTH | SOP YEAR |
|------------|------------|----------|--------------|--------|----------|------------|-----------|----------|--------|--------------|---------|-----------|----------|
| ABC000123 | 2014-04-11 | approval | Art 01 | 17890 | ACME | Dept. A | 0 | 21019 | Europe | ABC | (null) | 10 | 2014 |
| ABC000123 | 2014-04-11 | project | (null) | (null) | (null) | (null) | (null) | (null) | (null) | (null) | -0,020 | (null) | (null) |
| DEF000123 | 2014-05-11 | approval | Art 02 | (null) | (null) | (null) | (null) | (null) | (null) | DEF | (null) | (null) | (null) |
答案 1 :(得分:0)
如果您知道所有值,就可以执行此操作。然后你可以编写一个数据透视查询。我倾向于使用条件聚合来支持枢纽:
create view v_table as
select docid, date,
max(case when column2 = 'project name' then column3 end) as ProjectName,
. . .
from table t
group by docid, date;
这是对你想要的结构的猜测(每个文档和日期一行)。
在添加新列名时,您必须修改视图。