查询以组合一列中的多个列

时间:2014-03-31 20:01:05

标签: sql sql-server tsql pivot

我有包含以下信息的表格。 enter image description here

我想运行查询并只显示一行。这样的事情 enter image description here

我尝试使用案例陈述,但我可能有其他员工在不同的州工作,我不想列出50州,因为大多数员工可能只工作2-3州,但处于不同的状态。任何帮助将不胜感激。感谢

1 个答案:

答案 0 :(得分:2)

由于您想要在多个列上进行数据透视,我的建议是首先查看对StateStateWagesStateTax列进行取消隐藏,然后应用PIVOT函数。

您没有指定正在使用的SQL Server版本,但您可以使用UNPIVOT到CROSS APPLY将这些多列转换为行。语法类似于:

select PRCo, Employee, 
  col = c.col + cast(seq as varchar(50)),
  c.value
from
(
  select PRCo, Employee, State, StateWages, StateTax,
    row_number() over(partition by PRCo, Employee
                      order by state) seq
  from yourtable
) d
cross apply
(
  select 'State', State union all
  select 'StateWages', cast(StateWages as varchar(10)) union all
  select 'StateTax', cast(StateTax as varchar(10))
) c (col, value);

SQL Fiddle with Demo。您注意到在我实现CROSS APPLY之前,我使用了一个带有row_number()的子查询为每个员工的每一行创建一个唯一值。执行此操作的原因是您可以返回多个状态列等。完成此操作后,您可以使用PIVOT:

select PRCo, Employee, 
  State1, StateWages1, StateTax1,
  State2, StateWages2, StateTax2
from
(
  select PRCo, Employee, 
    col = c.col + cast(seq as varchar(50)),
    c.value
  from
  (
    select PRCo, Employee, State, StateWages, StateTax,
      row_number() over(partition by PRCo, Employee
                        order by state) seq
    from yourtable
  ) d
  cross apply
  (
    select 'State', State union all
    select 'StateWages', cast(StateWages as varchar(10)) union all
    select 'StateTax', cast(StateTax as varchar(10))
  ) c (col, value)
) src
pivot
(
  max(value)
  for col in (State1, StateWages1, StateTax1,
              State2, StateWages2, StateTax2)
) p;

SQL Fiddle with Demo。如果你的数值有限,上面的版本效果很好,但听起来你需要一个动态的解决方案。使用上面的代码,您可以轻松地将其转换为动态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 PRCo, Employee
                                 order by state) seq
                        from yourtable
                    ) d
                    cross apply
                    (
                      select 'State', 1 union all
                      select 'StateWages', 2 union all
                      select 'StateTax', 3
                    ) c (col, so)
                    group by col, so, seq
                    order by seq, so
            FOR XML PATH(''), TYPE
            ).value('.', 'NVARCHAR(MAX)') 
        ,1,1,'')


set @query = N'SELECT PRCo, Employee, ' + @cols + N' 
            from 
            (
              select PRCo, Employee, 
                col = c.col + cast(seq as varchar(50)),
                c.value
              from
              (
                select PRCo, Employee, State, StateWages, StateTax,
                  row_number() over(partition by PRCo, Employee
                                    order by state) seq
                from yourtable
              ) d
              cross apply
              (
                select ''State'', State union all
                select ''StateWages'', cast(StateWages as varchar(10)) union all
                select ''StateTax'', cast(StateTax as varchar(10))
              ) c (col, value)
            ) x
            pivot 
            (
                max(value)
                for col in (' + @cols + N')
            ) p '

exec sp_executesql @query;

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

| PRCO | EMPLOYEE | STATE1 | STATEWAGES1 | STATETAX1 | STATE2 | STATEWAGES2 | STATETAX2 |
|------|----------|--------|-------------|-----------|--------|-------------|-----------|
|    1 |      304 |     CA |    20162.03 |    804.42 |     IN |    20162.03 |    665.90 |