TSQL - 列标题的行值,包括更多列值

时间:2014-12-02 14:22:51

标签: sql sql-server tsql sql-server-2012 pivot

我的输入是包含以下列的视图:

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。

我很高兴看到一些示例代码。

谢谢。

2 个答案:

答案 0 :(得分:2)

您似乎需要首先忽略列Column3Column4Column5以返回非空行,然后转动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;

这是对你想要的结构的猜测(每个文档和日期一行)。

在添加新列名时,您必须修改视图。