简体   繁体   中英

Multiple rows of data into a single row - SQL Server

I have a table which looks a little like this

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

The table contains vast amounts of data, similar in structure to this. What I am trying to do is almost concatenate some of the data from multiple rows into a single row structure based on the student and the module taken, so the end result would look something like

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

So the new table would display all the end dates on the same row based on the module, and then the most recent mark 'max(Mark)' would be displayed. There are likely to be more than 3 possible End Dates as is displayed in the example table as this will depend entirely on the original table and how many times a student may have had to 'resit' a module (could be up to 4/5 times in some cases).

Try using Dynamic Pivot :

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

Check details of Pivot and Unpivot here .

NOTE : As you can see, I used a sub-query to find the latest Mark . I tried my best to replace it with something better but I couldn't. Still, it will work for you.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM