'mysqli subquery unknown column

This almost seems like a scope issue- the select statement in the subquery doesn't recognize table 'candidate':

SELECT 
        candidate.id AS id, 
        candidate.image AS image, 
        candidate.name AS name, 
        candidate.party AS party, 
        player.order AS player_order,
        c_pcts.pct AS pct
FROM  `candidate` 
INNER JOIN players player ON player.candidate_id = candidate.id 
INNER JOIN lineups lineup ON player.lineup_id = lineup.id 
INNER JOIN (
    SELECT 
        pct
    FROM candidate_pcts p
    INNER JOIN weekly_game game ON p.weekly_game_id = (
        SELECT id FROM weekly_game ORDER BY date DESC LIMIT 1
    ) WHERE p.candidate_id = candidate.id 
    ) c_pcts
WHERE lineup.id = '31' 
ORDER BY player.order ASC

gives the error: "Unknown column 'candidate.id' in 'where clause'." If instead of "FROM candidate_pcts p" I put

FROM candidate_pcts p, candidate c

then it doesn't see 'p.weekly_game_id' ...huh?

Seems like I need to identify the 'candidate' table for the subquery somehow but everything I'm trying leads me only further astray. And I have tried a mess of things: order of the tables, explicitly identifying them everywhere i could think of, backticks. I should note that the nested subquery works like a charm. Here it is again:

SELECT 
        pct
    FROM `candidate_pcts` 
    INNER JOIN weekly_game game ON candidate_pcts.weekly_game_id = (
        SELECT id FROM weekly_game ORDER BY date DESC LIMIT 1
    ) WHERE candidate_pcts.candidate_id = '5'

with a hardcoded an id value there, of course. I can supply database structure if needed here, but this is long already. The 'weekly_game' table is simply a set of scores for each candidate each week and we only want the most recent week's score, thus the 'ORDER BY date DESC LIMIT 1' clause.

Thanks very much for your time.


Tables:

  • table candidate:

    {id, image, name, party}

  • table candidate_pcts:

    {id, candidate_id, pct, weekly_game_id}

  • table lineups:

    {id, date, user_id}

  • table players:

    {id,candidate_id,lineup_id,order}

  • table weekly_game:

    {id,date}



Solution 1:[1]

You are basically on the right track around the problem. In essence the nested sub-select does not know about candidate.id. It you break apart the query and just look at the sub-select in question:

SELECT 
    pct
FROM candidate_pcts p
INNER JOIN weekly_game game ON p.weekly_game_id = (
    SELECT id FROM weekly_game ORDER BY date DESC LIMIT 1
) WHERE p.candidate_id = candidate.id 

You can see there is NO reference whatsoever in that query to the candidate table other than in your where clause, thus this is an unknown column.

Since a subselect is, in essence, made before the outer select that references it, the subselect must be a standalone, executable query.

Solution 2:[2]

Thanks to all, especially Mike for that excellent explanation. What I did was restructured the query like so:

SELECT 
        candidate.id AS id, 
        candidate.image AS image, 
        candidate.name AS name, 
        candidate.party AS party, 
        player.order AS player_order, 
        pcts.pct AS pct
FROM  `candidate` 
INNER JOIN players player ON player.candidate_id = candidate.id 
INNER JOIN lineups lineup ON player.lineup_id = lineup.id
LEFT JOIN (
    SELECT 
        p.candidate_id AS pct_id, pct AS pct
    FROM candidate_pcts p
    INNER JOIN weekly_game game ON p.weekly_game_id = (
        SELECT id FROM weekly_game ORDER BY date DESC LIMIT 1
    ) 
    ) pcts
        ON pct_id = candidate.id
WHERE lineup.id = '$lineup_id'
ORDER BY player.order ASC

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Richard Grove