Emmanuel
Emmanuel

Reputation: 5403

How to do a MYSQL conditional select statement

Background

I'm faced with the following problem, relating to three tables

class_sectors table contains three categories of classes

classes table contains a list of classes students can attend

class_choices contains the first, second and third class choice of the student, for each sector. So for sector 1 Student_A has class_1 as first choihce, class_3 as second choice and class_10 as third choice for example, then for sector 2 he has another three choices, etc...

The class_choices table has these columns:

kp_choice_id | kf_personID | kf_sectorID | kf_classID | preference | assigned

I think the column names are self explanatory. preference is either 1, 2 or 3. And assigned is a boolean set to 1 once we have reviewed a student's choices and assigned them to a class.

Problem:

Writing an sql query that tells the students what class they are assigned to for each sector. If their class hasn't been assigned, it should default to show their first preference.

I have actually got this to work, but using two (very bloated??) sql queries as follows:

$choices = $db -> Q("SELECT
    *, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
    `class_choices`
WHERE
    (`assigned` = '1')
GROUP BY
    `concatids`
ORDER BY
    `kf_personIDID` ASC,
    `kf_sectorID` ASC;");

$choices2 = $db -> Q("SELECT
    *, concat_ws(':', `kf_personID`, `kf_sectorID`) AS `concatids`
FROM
    `class_choices`
WHERE
    `preference` = '1'
GROUP BY
    `concatids`
HAVING
    `concatids` NOT IN (".iimplode($choices).")
ORDER BY
    `kf_personID` ASC,
    `kf_sectorID` ASC;");

if(is_array($choices2)){
    $choices = array_merge($choices,$choices2);
}

Now $choices does have what I want.

But I'm sure there is a way to simplify this, merge the two SQL queries, and so it's a bit more lightweight.

Is there some kind of conditional SQL query that can do this???

Upvotes: 1

Views: 218

Answers (1)

Marc Audet
Marc Audet

Reputation: 46825

Your solution uses two steps to enable you to filter the data as needed. Since you are generating a report, this is a pretty good approach even if it looks a bit more verbose than you might like.

The advantage of this approach is that it is much easier to debug and maintain, a big plus.

To improve the situation, you need to consider the data structure itself. When I look at the class_choices table, I see the following fields: kf_classID, preference, assigned which contain the key information.

For each class, the assigned field is either 0 (default) or 1 (when the class preference is assigned for the student). By default, the class with preference = 1 is the assigned one since you display it in the report when assigned=0 for all the student's class choices in a particular sector.

The data model could be improved by imposing a business rule as follows:
For preference=1 set the default value assigned=1. When the class selection process takes place, and if the student gets assigned the 2nd or 3rd choice, then preference 1 is unassigned and the alternate choice assigned.

This means a bit more code in the application but it makes the reporting a bit easier.

The source of the difficulty is that the assignment process does not explicitly assign the 1st preference. It only updates assigned if the student cannot get the 1st choice.

In summary, your SQL is good and the improvements come from taking another look at the data model.

Hope this helps, and good luck with the work!

Upvotes: 1

Related Questions