Lukasz G. Lukasz G. - 15 days ago 9
MySQL Question

MySQL outer query reference in a union subquery not working

Could anyone help me rebuild the following MySQL query so it works:

SELECT c.id, COUNT(DISTINCT d.student_id) FROM contract c, (
SELECT student_id FROM ilc_course ic, contract_seat cs2
WHERE c.id = cs2.contract
AND cs2.id = ic.contract_seat
AND ic.valid = 1 AND cs2.valid = 1
AND (ic.finished IS NULL OR ic.finished > CURRENT_TIMESTAMP)
UNION
SELECT student_id FROM glc_to_user_profile_student gtups, glc_course gc, contract_seat cs2
WHERE c.id = cs2.contract
AND gtups.contract_seat = cs2.id AND gtups.glc_course = gc.id
AND gtups.valid = 1 AND gc.valid = 1 AND cs2.valid = 1
AND (gtups.left_date IS NULL OR gtups.left_date > CURRENT_TIMESTAMP)
AND (gc.end_date IS NULL OR gc.end_date > CURRENT_TIMESTAMP)
) d GROUP BY c.id;


The query is supposed to count all distinct students from two sources and group them by the contract.

The problem is the subquery reference to c.id. Clearly, the subqueries don't know anything about the contract table.

I would very much appreciate help making it work.

Thanks!

Answer

You need to select cs2.contract in the subqueries, and then join that with c.id in the outer query.

SELECT c.id, COUNT(d.student_id) 
FROM contract c
JOIN (
    SELECT cs2.contract, student_id 
    FROM ilc_course ic
    JOIN contract_seat cs2 ON cs2.id = ic.contract_seat
    WHERE ic.valid = 1 AND cs2.valid = 1
        AND (ic.finished IS NULL OR ic.finished > CURRENT_TIMESTAMP)
    UNION
    SELECT cs2.contract, student_id 
    FROM glc_to_user_profile_student gtups
    JOIN glc_course gc ON gtups.glc_course = gc.id
    JOIN contract_seat cs2 ON gtups.contract_seat = cs2.id 
    WHERE gtups.valid = 1 AND gc.valid = 1 AND cs2.valid = 1
        AND (gtups.left_date IS NULL OR gtups.left_date > CURRENT_TIMESTAMP)
        AND (gc.end_date IS NULL OR gc.end_date > CURRENT_TIMESTAMP)
) d ON c.id = d.contract
GROUP BY c.id;

Also, since UNION removes duplicates from the subqueries, you don't need to use DISTINCT in COUNT().