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.