1

I have students work system. Each student can submit multiple assignments, and the assignments are either written or practical. For each student, I need to know who has ONLY submitted practical work, no written work.

I have two tables in use: assignments and workTypes.

assignments looks something like this (excuse date format):

userid   workID   submissionDate
--------------------------------
1        254      1/1/2022
1        723      0000-00-00
1        435      3/1/2022
1        845      4/2/2022
2        254      6/2/2022
2        435      2/6/2022
2        923      0000-00-00
2        845      6/2/2022

WorkTypes looks something like this:

workID     type
--------------------
254        written
435        practical
845        written
723        written
923        practical

SQL Executed:

SELECT 
    assignments.userid,
    GROUP_CONCAT(case when workTypes.type = 'written' AND assignments.submissionDate IS NOT NULL AND assignments.submissionDate != '0000-00-00' then assignments.submissionDate end) AS 'writtenDates',
    COUNT('writtenDates') AS numWritten,
    GROUP_CONCAT(case when workTypes.type = 'practical' AND assignments.submissionDate IS NOT NULL AND assignments.submissionDate != '0000-00-00' then assignments.submissionDate end) AS 'practicalDates',
    COUNT('practicalDates') AS numPractical 
FROM `assignments` 
LEFT JOIN workTypes 
ON assignments.workID = workTypes.workID 
GROUP BY assignments.userid;

Expected Results:

userID    writtenDates        numWritten   practicalDates   numPractical
1         1/1/2022,4/2/2023   2            3/1/2022         1
2         6/2/2022,6/2/2022   2            2/6/2022         1

Once I have this data working, I want to add a clause to only select those results that have no written work but some practical, so something like:

HAVING numPractical > 0 AND numWritten < 1

At the moment, my query is returning the same number in the numWritten and numPractical fields for every student (4000+ students) which cannot be correct and also, the num fields are showing much higher numbers than there are dates, so for example I can see one row that has three dates in, but the numPractical field says 23. I am assuming 23 is the count of the number of rows of work for each student or something instead of the number of dates in the group_concat field, but I can't work out why.

1
  • I suggest just using NULL to represent a missing date. Commented Jan 15, 2023 at 12:07

1 Answer 1

1

Use conditional aggregation with a boolean expression:

SELECT 
    a.userid,
    GROUP_CONCAT(CASE WHEN wt.type = 'written' AND a.submissionDate IS NOT NULL AND
                           a.submissionDate != '0000-00-00'
                      THEN a.submissionDate END) AS writtenDates,
    COUNT(CASE WHEN wt.type = 'written' AND a.submissionDate IS NOT NULL AND
                    a.submissionDate != '0000-00-00'
               THEN 1 END) AS numWritten,
    GROUP_CONCAT(CASE WHEN wt.type = 'practical' AND a.submissionDate IS NOT NULL AND
                           a.submissionDate != '0000-00-00'
                      THEN a.submissionDate END) AS practicalDates,
    COUNT(CASE WHEN wt.type = 'practical' AND a.submissionDate IS NOT NULL AND
                           a.submissionDate != '0000-00-00'
                      THEN 1 END) AS numPractical 
FROM assignments a 
LEFT JOIN workTypes wt
    ON a.workID = wt.workID 
GROUP BY a.userid;
Sign up to request clarification or add additional context in comments.

6 Comments

Can I just check that this code will count the numbers of practical and written work ONLY if the dates are present for each type?
@Dan No...in that case you need to repeat the full CASE expressions.
Brilliant, thank you - also when I try to select only the records where the numPractical is more than 0 and the numWritten is less than 1 it comes up with an error. I am adding the following after the GROUP BY clause. Is it in the wrong place? WHERE numPractical > 0 AND numWritten < 1
Use: HAVING numPractical > 0 AND numWritten < 1 ... after GROUP BY
Thanks for your help - do you have any recommended reading material on how to get your head around how to properly structure these types of query?
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.