Using Microsoft SQL Server 2016 and a Moodle LMS database.
Is it possible to write this pivot code so that the 'Activity' names don't have to be hardcoded in the query?
SELECT * FROM (
SELECT
u.id,
u.firstname AS 'Name',
u.lastname AS 'Surname',
u.idnumber AS 'ID Number',
u.institution AS 'Division',
u.address AS 'Region',
u.department AS 'Branch',
ur.name AS 'Activity'
FROM mdl_course_modules_completion cmc
JOIN mdl_course_modules cm ON cm.id = cmc.coursemoduleid
JOIN mdl_course c ON c.id = cm.course
JOIN mdl_user u ON u.id = cmc.userid
JOIN mdl_url ur ON ur.id = cm.instance
WHERE cm.course IN (100,101,102)
AND cm.module IN (23,9,14,26) -- 23 = url, 9 = label, 14 = scorm, 26 = assign
) SOURCE
PIVOT (
COUNT(id)
FOR Activity IN (
[Activity ABC123],
[Activity DEF234],
[Activity GHI567],
[Activity JKL890],
[Activity MNO987],
[Activity PQR657],
[Activity STU814]
)
) PIVT
ORDER BY Surname
I would prefer to get the 'Activity' names from this query instead of hardcoding them:
SELECT ur.name
FROM mdl_url ur
JOIN mdl_course_modules cm ON ur.id = cm.instance
WHERE cm.course IN (100,101,102)
Which gives me:
name
Activity ABC123
Activity DEF234
Activity GHI567
Activity JKL890
Activity MNO987
Activity PQR657
Activity STU814
I've tried this dynamic sql:
DECLARE @cols AS NVARCHAR(MAX),
@query AS NVARCHAR(MAX);
SET @cols = STUFF((SELECT distinct ',' + QUOTENAME(ur.name)
FROM mdl_url ur
JOIN mdl_course_modules cm ON ur.id = cm.instance
WHERE cm.course IN (100,101,102)
FOR XML PATH(''), TYPE
).value('.', 'NVARCHAR(MAX)')
,1,1,'')
select @cols
set @query = 'SELECT *, ' + @cols + ' FROM
(
SELECT
u.id,
u.firstname AS Name,
u.lastname AS Surname,
u.idnumber AS ID_Number,
u.institution AS Division,
u.address AS Region,
u.department AS Branch,
ur.name AS Activity
FROM mdl_course_modules_completion cmc
JOIN mdl_course_modules cm ON cm.id = cmc.coursemoduleid
JOIN mdl_course c ON c.id = cm.course
JOIN mdl_user u ON u.id = cmc.userid
JOIN mdl_url ur ON ur.id = cm.instance
WHERE cm.course IN (100,101,102)
AND cm.module IN (23,9,14,26)
) x
pivot
(
COUNT(id)
for Activity in (' + @cols + ')
) p '
execute(@query)
But it's giving me errors:
Msg 207, Level 16, State 1, Line 22
Invalid column name 'Value'.
Msg 207, Level 16, State 1, Line 23
Invalid column name 'Point'.
So, my 2 questions are:
- What am I doing wrong in the above code?
- Is it possible to do the above without using dynamic sql?
Thanks