【问题标题】:How to convert multiple rows to one row in SQL Server? [duplicate]如何在 SQL Server 中将多行转换为一行? [复制]
【发布时间】:2014-12-30 20:50:50
【问题描述】:

我的查询有问题。假设我有两个名为PersonInfoPersonEducation 的表。我用StudentId 对这些表应用了连接操作,结果是这样的。

   StudentIdId      Name    University    Department     Status
   ---------------------------------------------------------------
      1             John    Cambridge     Computer       Graduated
      1             John    Berkeley      Mathematic     Graduated
      1             John    Boston        Economy        Ongoing

这只是学生(约翰)的一个例子。这表明约翰毕业于 2 所大学,但仍在一所大学学习。大学人数可能会因学生而异。我的问题是,我怎样才能在 1 行中显示这 3 行。我的意思是我想在一行中显示所有教育信息,以免一个人有多行。

提前感谢您的帮助。

【问题讨论】:

  • 你先试试怎么样?
  • 您能向我们展示您希望您的数据是什么样子的样本吗?
  • 如果约翰在 5 所大学学习会怎样?任何给定学生可以获取数据的大学数量是否有硬性限制?

标签: sql sql-server join inner-join multirow


【解决方案1】:

测试数据

DECLARE @TABLE TABLE (StudentIdId INT, Name VARCHAR(100), University VARCHAR(100)
                       , Department VARCHAR(100),[Status] VARCHAR(100))
INSERT INTO @TABLE VALUES 
(1 ,'John','Cambridge','Computer'  ,'Graduated'),
(1 ,'John','Berkeley' ,'Mathematic','Graduated'),
(1 ,'John','Boston'   ,'Economy'   ,'Ongoing'),
(2 ,'Pete','Cambridge','Computer'  ,'Graduated'),
(2 ,'Pete','Berkeley' ,'Mathematic','Graduated')

查询

SELECT t.StudentIdId
      ,t.Name
      ,STUFF((SELECT ', ' + University 
              FROM @TABLE 
              WHERE StudentIdId = t.StudentIdId
              FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,'') AS University
      ,STUFF((SELECT ', ' + Department 
              FROM @TABLE 
              WHERE StudentIdId = t.StudentIdId
              FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,'') AS Department
      ,STUFF((SELECT ', ' + [Status] 
              FROM @TABLE 
              WHERE StudentIdId = t.StudentIdId
              FOR XML PATH(''),TYPE).value('.','NVARCHAR(MAX)'),1,2,'') AS [Status]

FROM @TABLE t 
GROUP BY t.StudentIdId ,t.Name

结果

╔═════════════╦══════╦═════════════════════════════╦═══════════════════════════════╦═══════════════════════════════╗
║ StudentIdId ║ Name ║         University          ║          Department           ║            Status             ║
╠═════════════╬══════╬═════════════════════════════╬═══════════════════════════════╬═══════════════════════════════╣
║           1 ║ John ║ Cambridge, Berkeley, Boston ║ Computer, Mathematic, Economy ║ Graduated, Graduated, Ongoing ║
║           2 ║ Pete ║ Cambridge, Berkeley         ║ Computer, Mathematic          ║ Graduated, Graduated          ║
╚═════════════╩══════╩═════════════════════════════╩═══════════════════════════════╩═══════════════════════════════╝

【讨论】:

    【解决方案2】:

    这取决于你想要的输出。

    1. 如果要聚合 PersonEducation 中的数据以计算状态,则可以加入 PersonEducation 表的子查询。有很多关于如何使用子查询以及如何按字段分组的文章。

    类似:

    SELECT pere.StudentId
        , pere.StudentName
        , peri.UniversityCount
        , peri.GraduatedStatusCout
        , peri.OngoingStatusCount
    FROM PersonInfo peri
    LEFT JOIN
        (SELECT StudentId
            , UniversityCount = COUNT(*)
            , GraduatedStatusCount = SUM(IIF(Status = 'Graduated', 1, 0))
            , OngoingStatusCount = SUM(IIF(Status = 'Ongoing', 1, 0))
        FROM PersonEducation
        GROUP BY StudentId) pere
        ON peri.StudentId = pere.StudentId;
    
    1. 如果您想获得最后一所大学就读,那么您将需要某个日期就读领域。有人可能同时就读不止一所大学,因此您需要关于如何挑选获胜者的规则。不过,在这些情况下,您可以使用 ROW_NUMBER() in an OVER() 子句对数据进行排序并过滤结果。

    2. 您可以按照here 或任何数量的其他文章中所述将数据连接在一起。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-12-22
      • 2020-11-14
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多