Search code examples
sqldatabasephpbb

SQL: Retrieving custom profile field, banned status and inactive status


I'm attempting to create a PHP file that will open up my PHPBB3 database and retrieve a list of all the Minecraft usernames on the forum which will be used as a whitelist on the associated game server. The username (urbb_profile_fields_data.pf_mcusername) needs to be filtered by the following: The username is not null, is not blank, is not banned (ID does not match an ID within urbb_banlist.ban_userid) and has been activated (urbb_users.user_inactive_reason is 0).

My knowledge of SQL is admittedly very poor, but I have got this completely working and implemented:

SELECT urbb_profile_fields_data.pf_mcusername, urbb_profile_fields_data.user_id, urbb_banlist.ban_userid FROM urbb_profile_fields_data, urbb_banlist WHERE ((pf_mcusername IS NOT NULL) AND (pf_mcusername <> '')) AND ban_userid != urbb_profile_fields_data.user_id

However, when I attempt to use: urbb_users.user_inactive_reason within SELECT and urbb.users within FROM, SQL will retrieve over 7000 results that appear to loop and over. This happens as soon as I enter urbb_users in FROM.

Undoubtedly there's something that I'm missing here because I'm not really familiar with JOIN (I've read a few tutorials on it) so I'm hoping someone can help out here!

Thanks.


Solution

  • There is a substantial problem with your implementation of the query. It shouldn't actually work even without any other tables involved.

    What "FROM A, B" means in SQL is "Make another table which has all the fields of both A and B and its lines are all possible combinations from both A anb B" and select from there. So, say you have 4 lines in each table the resulting table will have 16 lines. To filter unneccessary lines, you use a condition, "WHERE A.user_id = B.user_id". That way the resulting table will have only lines both parts of which correspond to actually the same user.

    Your query though has "WHERE A.user_id != B.user_id" and should return a looped set of all lines in which both parts do not match. If you have only 1 player in banned list it will work, but if there are atleast 2, not only it will loop, it will also let banned players into the resulting list. Also, if you have NO banned users, the query result will be empty.

    The proper query would look like this:

    SELECT A.username, B.user_id FROM A LEFT JOIN B ON A.user_id = B.banned_id
    WHERE B.banned_id IS NULL
    

    Basically, you look for rows in table A that have no match in table B. To add other tables into the query you need to hook them up like that:

    SELECT A.username, B.user_id FROM A LEFT JOIN B ON A.user_id = B.banned_id
    LEFT JOIN C ON A.user_id = C.user_id WHERE B.banned_id IS NULL
    

    Hope it helps...