将多行数据合并到一行中-SQL Server

将多行数据合并到一行中-SQL Server,sql,sql-server,Sql,Sql Server,我有一张有点像这样的桌子 ID NAME MODULE STARTDATE ENDDATE MARK 123456 J Bloggs Module 1 13/01/2014 30/04/2014 FAIL 123456 J Bloggs Module 1 13/05/2014 30/08/2014

我有一张有点像这样的桌子

ID          NAME          MODULE          STARTDATE          ENDDATE          MARK
123456      J Bloggs      Module 1        13/01/2014         30/04/2014       FAIL
123456      J Bloggs      Module 1        13/05/2014         30/08/2014       FAIL
123456      J Bloggs      Module 1        13/09/2014         30/12/2014       PASS
123456      J Bloggs      Module 2        13/05/2014         30/08/2014       PASS
123456      J Bloggs      Module 3        13/01/2015         30/04/2015       FAIL
234567      A Test        Module 1        13/01/2014         30/04/2014       PASS
234567      A Test        Module 2        13/05/2014         30/08/2014       FAIL
234567      A Test        Module 2        13/09/2014         30/12/2014       PASS
该表包含大量数据,结构与此类似。我试图做的是,基于学生和所取模块,将多行中的一些数据连接到一个单行结构中,因此最终结果类似于

ID          NAME          MODULE          ENDDATE1          ENDDATE2          ENDDATE3          MARK
123456      J Bloggs      Module 1        30/04/2014        30/08/2014        30/12/2014        PASS
123456      J Bloggs      Module 2        30/08/2014                                            PASS
123456      J Bloggs      Module 3        30/04/2015                                            FAIL
234567      A Test        Module 1        30/04/2014                                            PASS
234567      A Test        Module 2        30/08/2014        30/12/2014                          PASS

因此,新表将基于模块在同一行上显示所有结束日期,然后显示最近的标记“max(mark)”。示例表中可能会显示3个以上的可能结束日期,因为这将完全取决于原始表以及学生可能“重设”模块的次数(在某些情况下可能多达4/5次)。

尝试使用动态透视:

IF(OBJECT_ID('tempdb..#table') IS NOT NULL)
DROP TABLE #TABLE
CREATE TABLE  #TABLE (ID INT, NAME VARCHAR(30),MODULE VARCHAR(30),STARTDATE VARCHAR(30),ENDDATE VARCHAR(30),MARK VARCHAR(30))

INSERT INTO #TABLE VALUES
(123456, 'J Bloggs', 'Module 1', '13/01/2014', '30/04/2014', 'FAIL'),
(123456, 'J Bloggs', 'Module 1', '13/05/2014', '30/08/2014', 'FAIL'),
(123456, 'J Bloggs', 'Module 1', '13/09/2014', '30/12/2014', 'PASS'),
(123456, 'J Bloggs', 'Module 2', '13/05/2014', '30/08/2014', 'PASS'),
(123456, 'J Bloggs', 'Module 3', '13/01/2015', '30/04/2015', 'FAIL'),
(234567, 'A Test', 'Module 1', '13/01/2014', '30/04/2014', 'PASS'),
(234567, 'A Test', 'Module 2', '13/05/2014', '30/08/2014', 'FAIL'),
(234567, 'A Test', 'Module 2', '13/09/2014', '30/12/2014', 'PASS')
DECLARE @Columns VARCHAR(MAX)

SELECT @Columns = STUFF((SELECT ',' + '[' + CONVERT(VARCHAR(30), number, 121) + ']'
                         FROM   master..spt_values N
                         WHERE  n.number BETWEEN 1 AND (SELECT TOP 1 COUNT(Enddate)
                                                        FROM   #TABLE
                                                        GROUP  BY ID,NAME,MODULE
                                                        ORDER  BY COUNT(Enddate) DESC)
                                AND TYPE = 'P'
                         FOR XML PATH('')), 1, 1, '')
DECLARE @sql NVARCHAR(MAX) = '
SELECT ID,
       NAME,
       MODULE,
       '+@Columns+',
       (SELECT TOP 1 MARK
        FROM   #table t1
        WHERE  pvt.ID = t1.ID
               AND pvt.NAME = t1.NAME
               AND pvt.MODULE = t1.MODULE
        ORDER  BY enddate DESC) AS MARK
FROM   (SELECT ID,
               NAME,
               MODULE,
               ENDDATE,
               ROW_NUMBER()
                 OVER(
                   partition BY ID, NAME, MODULE
                   ORDER BY enddate) AS rn
        FROM   #table) t
       PIVOT ( Max(ENDDATE)
             FOR rn IN('+@Columns+')) AS pvt 
'

EXEC sp_executeSQL @sql
检查轴和取消轴的详细信息


注意:如您所见,我使用了一个子查询来查找最新的
标记
。我尽力用更好的东西来代替它,但我做不到。尽管如此,它仍然适用于您。

是否最多只能有3个结束日期,或者可以有更多的结束日期?我建议您使用最后3个日期,并可能添加另一列,说明除显示的3个日期之外的其他尝试的数量。否则你会有很多可能,因为我的学生会一次又一次地失败。或者只显示其他尝试的最后结果、标记和计数,因为其他尝试无论如何都将失败。然后,如果你想要特定的测试数据,你可以钻取其中的数据。如果你选择了我们可以使用的最大日期数?我会说,看到超过5个日期会令人惊讶