将SQL Row值转换为列

时间:2018-06-16 14:38:23

标签: sql sql-server

我有一个Employee表,当我按照SQL执行查询时给出以下结果:

 Select ID, Role as "Role Name", Employee as "Employee Name"
from employee

Query Result

现在,我想按照下图转换上面的查询结果。我使用了最大和最小的Pivot&然后做了工会,但它只提供了与角色名称相对应的两个员工姓名。我需要得到如下结果。有什么建议吗?

Expected Output

3 个答案:

答案 0 :(得分:3)

select
       id,

       case when [Role Name] = 'Consultant' 
            then [Employee Name] else null 
       end as Consultant,

       case when [Role Name] = 'Manager' 
            then [Employee Name] else null 
       end as Manager
from
     employee

如果您有其他角色,可以添加更多案例陈述

使用Pivot,

select 
    id,
    Consultant, 
    Manager
from 
    ( select 
        id,
        [Role Name],
        [Employee Name], 
        row_number() over( partition by id order by id) as rn 
      from 
        employee
    ) src 
pivot 
    ( max([Employee Name]) for [Role Name] in (Consultant,Manager) ) as pvt ;

更新

如果您有多个角色或非固定数量的角色,这可能不是一个好的解决方案。

一种方法是dynamic pivot

答案 1 :(得分:1)

`Jophab的方法是一种非常好的方法。如果您正在学习SQL,请考虑以下另一种方法:

select id, employeename as consultant, null as manager
from employee
where rolename = 'Consultant'
union all
select id, null as employeename as manager
from employee
where rolename = 'Manager';

这需要两次扫描employee表 - 这对于小表来说非常简单。

编辑:

另一种不需要大量case表达式的方法使用join

select e.id, v.*
from employee e join
     (values ('consultant', employeename, null),
             ('manager',  null, employeename)
     ) v(rolename, consultant, manager)
     on e.rolename = v.rolename;

但是,您必须为null中的每一行键入一堆values()个。

答案 2 :(得分:1)

如果您拥有的角色数量可以改变,这是一个未来证明的答案;因此你需要改变你的SQL。这避免了这种需要,但是(像Gordan当前的答案一样)需要对表进行2次扫描:

CREATE TABLE Employee (ID int, [Role] varchar(10), Employee varchar(15));

INSERT INTO Employee
VALUES (1, 'Manager','Steve'),
       (2, 'Consultant','Jayne');

GO
--Hard coded SQL solution

SELECT ID,
       CASE [Role] WHEN 'Manager' THEN Employee END AS Manager,
       CASE [Role] WHEN 'Consultant' THEN Employee END AS Consultant
FROM Employee;
GO
--Now, let's add a another role, and try the SQL again:
INSERT INTO Employee
VALUES (3, 'Director','Sally');
SELECT ID,
       CASE [Role] WHEN 'Manager' THEN Employee END AS Manager,
       CASE [Role] WHEN 'Consultant' THEN Employee END AS Consultant
FROM Employee;
--Unsurprisingly, Sally doesn't appear, but a "blank" row does
GO
--Dynamic SQL solution:
DECLARE @SQL nvarchar(MAX);

SET @SQL = N'SELECT ID,' +NCHAR(10) +
           STUFF((SELECT DISTINCT N',' + NCHAR(10) +
                                  N'       CASE [Role] WHEN ' + QUOTENAME([Role],N'''') + N' THEN Employee END AS ' + QUOTENAME([Role])
                  FROM Employee
                  FOR XML PATH(N'')),1,2,N'') + NCHAR(10) +
           N'FROM Employee;';
PRINT @SQL; --your best friend
EXEC sp_executesql @SQL;
GO

DROP TABLE Employee;