I did my homework and looked for information on the net and in StackOverflow but I did not find an answer to my question. I looked at:
Creating two colums from rows of a table (did not understand it) MySQL join same table display rows in columns way (complicated) (different and problem does not seem the same) Creating two colums from rows of a table
I used this to build my query:
How to Display rows as Columns in MySQL?
I have a table "lessons" that goes like this:
ID  title
---------
1   Math
2   Latin
3   English
4   Science 
I have a second table "results" that stores the type of test user have passed for each lesson. There are currently two types of tests: o and w (there could be more in the future). The table goes like this:
lesson_id  usr_id  test_type   course_id
----------------------------------------
1          100       o          1
1          100       w          1
1          24        o          1
1          36        w          1
In the table above user 100 passed test o and w for the Math. In the table above user 24 passed test o for the Math. In the table above user 36 passed test w for the Math.
Now I would like to get a report for user 100, I would like to have something like:
ID  title      o       w
------------------------------
1    Math       TRUE    TRUE
2    Latin      FALSE   FALSE
3    English    FALSE   FALSE
4    Science    FALSE   FALSE
For user 36:
ID  title      o       w
------------------------------
1    Math       FALSE    TRUE
2    Latin      FALSE   FALSE
...
For user 24:
ID  title      o       w
------------------------------
1    Math       TRUE    FALSE
2    Latin      FALSE   FALSE
...
Any other user:
ID  title      o       w
------------------------------
1    Math       FALSE   FALSE
2    Latin      FALSE   FALSE
...
I can accomplish this with a query as follows:
SELECT l.id, l.title, COALESCE(s.o,FALSE) AS o, COALESCE(t.w, FALSE) AS w FROM lessons l 
LEFT JOIN (
    SELECT r.lesson_id,
    CASE
        WHEN r.test_type='o' THEN TRUE
        ELSE FALSE
    END AS o
    FROM results r WHERE r.itype='o' AND r.usr_id=100
    ) AS s ON l.id=s.lesson_id 
LEFT JOIN (
    SELECT rr.lesson_id,
    CASE
        WHEN rr.test_type='w' THEN TRUE
        ELSE FALSE
    END AS w 
    FROM results rr WHERE rr.test_type='w' AND rr.usr_id=100
    ) AS t ON l.id=t.lesson_id
WHERE l.course_id=1 ORDER BY l.id ASC;
While this code seems to work (still busy testing it), I do not like it because it requires two joins and each join is made of selects from a table that could turn out to be quite large in the future. This query would be run often
Can you suggest a better way to do this (better can mean smarter, more straightforward, faster or other design... or any other suggestion :-) )?
In case I need to stick with this, could you recommend references as how to set the best indexes to run this query fast? Links, articles you used?
What happens where more test_types will be created? My query uses only w and o what if tomorrow there are more? Is there a generic way to do this kind of thing?
Any help / advice is more than welcome,
Philippe