【问题标题】:Transpose rows after Join and Groupby in SQL Server table在 SQL Server 表中加入和分组后转置行
【发布时间】:2020-09-12 05:32:54
【问题描述】:

我有一些 SQL Server 表:

  • 员工 [EmpID (pk)、姓名、职务]
  • 项目 [PID (pk)、EmpID (fk)、PCode、PName、Dept]

这些表是多对一的关系,也就是说,一个员工可以处理多个项目。

我想以这样一种方式显示结果,即每个员工只有一行,并且他从事的所有项目都显示在根据 PCode 分组的列部分中。

当生成的列数未知时,我无法理解如何将行转置到列中。

样本数据:

员工:

EmpId  Name  Designation
------------------------
001    Mat   Manager
002    Ash   Developer
003    Paul  Analyst

项目:

PID EmpID PCode PName       Dept
-------------------------------------
1   001   111   Project1    Sales
2   001   111   Project1.1  Retail
3   001   222   Project2    Banking
4   002   222   Project2.1  Retail   

样本输出:

EmpID Name Project-1           Project-2              Project-3           
---------------------------------------------------------------------------
001   Abc  111,Project1,Sales  111,Project1.1,Retail  222,Project2,Banking
002   Def  222,Project2.1,Retail

【问题讨论】:

  • 以表格格式提供样本数据和您想要的输出
  • 更新了问题。请检查
  • 你使用的是哪个版本的sql server
  • 请向我们展示您的尝试。

标签: sql-server string group-by pivot window-functions


【解决方案1】:

您可以使用row_number() 在子查询中枚举每个员工的项目,然后使用条件聚合在外部查询中进行透视:

select e.empid, e.name,
    max(case when rn = 1 then concat_ws(',', p.pcode, p.pname, p.pdept) end) project1,
    max(case when rn = 2 then concat_ws(',', p.pcode, p.pname, p.pdept) end) project2,
    max(case when rn = 3 then concat_ws(',', p.pcode, p.pname, p.pdept) end) project3
from employee e
inner join (
    select p.*, row_number() over(partition by empid order by pid) rn
    from projects p
) p on p.empid = e.empid
group by e.empid, e.name

【讨论】:

  • 它给了我这个错误“错误代码:1064 您的 SQL 语法有错误;请查看与您的 MySQL 服务器版本相对应的手册,以在 '(按 empid 顺序分区)附近使用正确的语法通过 pid) rn
  • @user8306074:这是一条 MySQL 错误消息。你为什么要标记你的问题 SQL Server? row_number() 我只在 MySQL 8.0 中可用。
  • 我有一个庞大的数据集,不知道每个员工的最大项目数。那么,在那种情况下,我如何生成多个项目列?
【解决方案2】:

您可以使用PIVOT 命令转置您的数据。对于您未知的情况,生成的列数是未知的。您需要查询生成列的列名,然后您可以使用PIVOT 命令将所有列名连接起来,如下查询语句。

DECLARE @columnName NVARCHAR(MAX), @pivotSql NVARCHAR(MAX)
SELECT 
    em.EmpID,
    em.Name,
    pr.Pname,
    pr.Pcode + ',' + pr.PName + ',' + pr.Dept Detail
INTO #temp
FROM Employee em 
INNER JOIN Projects pr ON em.EmpID = pr.EmpID 

SELECT 
    t.PName name
INTO #AllProject
FROM #temp t
GROUP BY t.PName

SET @columnName = '';

DECLARE 
    @projectName VARCHAR(MAX);

DECLARE cursor_allProject CURSOR
FOR SELECT 
        name
    FROM 
        #AllProject;
OPEN cursor_allProject;
FETCH NEXT FROM cursor_allProject INTO @projectName;
WHILE @@FETCH_STATUS = 0
    BEGIN
        SET @columnName = @columnName + ', [' + @projectName + ']';
        FETCH NEXT FROM cursor_allProject INTO @projectName;
    END;
CLOSE cursor_allProject;
DEALLOCATE cursor_allProject;


SET @pivotSql = 'SELECT t.EmpID, t.Name FROM #temp t PIVOT t.Detail (FOR t.Pname IN ('+ @columnName +') )'

EXEC (@pivotSql)

【讨论】:

  • 您使用的是哪个版本的 SQL?
  • 您可以与任何 SQL Server 一起使用
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-12-08
  • 1970-01-01
  • 2011-10-12
  • 2011-09-17
相关资源
最近更新 更多