Question

I have a database table full of user status updates. I want to output all these results, providing that the user that posted that status has not been blocked.

The WHERE clause IS being met.. but for some reason it's also deciding to only output status updates where the 'user id' is present within one of the tbl_blocking columns.

Obviously, if that user doesn't appear in the blocking table at any point (has never been blocked, or blocked anyone) their status should still be shown.

How can I overcome this? Where am I going wrong?

//Get status results
            $sql = "SELECT 

            tbl_status.id as statID, 
            tbl_status.from_user as statFROM, 
            tbl_status.status as statSTATUS, 
            tbl_status.deleted as statDEL, 
            tbl_status.date as statDATE,

            tbl_users.id as usrID, 
            tbl_users.name as usrNAME,
            tbl_users.location as usrLOCATION,
            tbl_users.postcode as usrPOSTCODE,

            tbl_blocking.id as blockID,
            tbl_blocking.user as blockUSER,
            tbl_blocking.blocking as blockBLOCKING,
            tbl_blocking.date as blockDATE,
            tbl_blocking.active as blockACTIVE

            FROM tbl_status 

            INNER JOIN tbl_users ON tbl_status.from_user = tbl_users.id
            INNER JOIN tbl_blocking ON tbl_users.id = tbl_blocking.user

            WHERE 
            tbl_status.deleted = '0'
            AND tbl_blocking.active = '0'
            AND tbl_blocking.user != :who
            AND tbl_blocking.blocking != :who

            ORDER BY 
            tbl_status.date desc

            LIMIT 200

            ";
Was it helpful?

Solution

You have to use LEFT JOIN if you want to get rows that have no match in the joined table. And then if you want to be able to select particular rows in the joining table, you have to include a specific NULL test to keep that row as well.

        $sql = "SELECT 

        tbl_status.id as statID, 
        tbl_status.from_user as statFROM, 
        tbl_status.status as statSTATUS, 
        tbl_status.deleted as statDEL, 
        tbl_status.date as statDATE,

        tbl_users.id as usrID, 
        tbl_users.name as usrNAME,
        tbl_users.location as usrLOCATION,
        tbl_users.postcode as usrPOSTCODE,

        tbl_blocking.id as blockID,
        tbl_blocking.user as blockUSER,
        tbl_blocking.blocking as blockBLOCKING,
        tbl_blocking.date as blockDATE,
        tbl_blocking.active as blockACTIVE

        FROM tbl_status 

        INNER JOIN tbl_users ON tbl_status.from_user = tbl_users.id
        LEFT JOIN tbl_blocking ON tbl_users.id = tbl_blocking.user

        WHERE 
        tbl_status.deleted = '0'
        AND (tbl_blocking.user IS NULL
            OR (tbl_blocking.active = '0'
                AND tbl_blocking.user != :who
                AND tbl_blocking.blocking != :who))

        ORDER BY 
        tbl_status.date desc

        LIMIT 200

        ";

OTHER TIPS

The problem is that you are joining against the blocking table. This means only users in the blocking table AND the users table will be shown. You want to left join BOTH tbl_blocking and tbl_blocking2 it seems. I'm not sure of your schema, as to why you join twice on the same table.

For example:

User  join Blocking

1,2,3       2,3

will return ids (assuming select user.id, blocking.id): 
2,2
3,3

This will OMIT user 1 as blocking does not contain id 1.

User  left join blocking

1,2,3          2,3

will return

1, null (this will be null since blocking does not contain an id of 1)
2, 2
3, 3 

This will include id 1 that you are missing.

Here is something to explain joins better: Joins

Excerpt of your mysql:

FROM tbl_status 
INNER JOIN tbl_users ON tbl_status.from_user = tbl_users.id
LEFT JOIN tbl_blocking ON tbl_users.id = tbl_blocking.user

Since status and user appears to be a 1 to 1 record a join there should be fine. The left join of blocking on user is necessary. This will provide all records of the user table no matter what is in the blocking table. I have included a resource to look at that will explain it further. I also can start a chat on here if that will help you.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top