Reputation: 45
Let's say that I have this one table which contain the student marks for each assessment (eg: quiz,test and etc).
This is the original table:
I wanted to convert the assessment type to be the column. This is the output that I want:
+---------------+------------+----------+
| student_name | Quiz 1 | QUIZ 2 |
+---------------+------------+----------+
| thaqif | 4.00 | 5.oo |
+---------------+------------+----------+
| ajis | 4.00 | 5.00 |
+---------------+------------+----------+
I am able to produce this with this algorithm:
SELECT student_name,
MAX(IF((`assessment_type` = 'QUIZ' AND `assessmet_no` = '1'), assessment_marks, NULL)) 'QUIZ 1',
MAX(IF((`assessment_type` = 'QUIZ' AND `assessmet_no` = '2'), assessment_marks, NULL)) 'QUIZ 2'
FROM studentmarks
GROUP BY student_name
However, in the real situation, the number of assessment type is unknown. The algorithm above is only useful if we have the fixed number of assessment_type.
In order to handle that, I have found an algorithm which I believed can solve the problem:
SET @sql = NULL;
SELECT
GROUP_CONCAT(
CONCAT(
'MAX(IF(`assessment_type` = ', `assessment_type`, ',assessment_marks, NULL)) AS ', `assessment_type`)
) INTO @sql
FROM studentmarks;
SET @sql = CONCAT('SELECT student_name, ', @sql, '
FROM studentmarks
GROUP BY student_name');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Unfortunately, this algorithm called this error:
#1054 - Unknown column 'QUIZ' in 'field list'
I have no idea on what's wrong with the algorithm. Fyi, I have gone through a few similar questions on SO but none of it seems to be working with my problem. These are some of the questions or information that I referred to:
Mysql query to dynamically convert rows to columns on the basis of two columns
http://buysql.com/mysql/14-how-to-automate-pivot-tables.html
Upvotes: 0
Views: 514
Reputation: 1269643
This is only slightly more complicated than a regular pivot because you need a condition on two columns:
select student_name,
max(case when assessment_type = 'QUIZ' and assesment_no = 1 then marks end) as quiz1,
max(case when assessment_type = 'QUIZ' and assesment_no = 2 then marks end) as quiz2
from student_marks
group by student_name;
You can expand this into dynamic SQL as:
SET @condition = 'MAX(CASE WHEN assessment_type = ''@at'' AND assement_no = @an THEN assessment_marks END) as @at@an';
SELECT @conditions := GROUP_CONCAT(REPLACE(REPLACE(@condition, '@at', assessment_type), '@an', assessment_no))
FROM studentmarks;
SET @sql = CONCAT('
SELECT student_name, ', @conditions, '
FROM studentmarks
GROUP BY student_name');
PREPARE stmt FROM @sql;
EXECUTE stmt;
DEALLOCATE PREPARE stmt;
Upvotes: 1