简体   繁体   中英

SQL Join query using three tables and some null values

I have three tables in a mySQL database that I am querying with PHP:

players

player_id | player_name
-----------------------
1           Tom
2           Dick
3           Harry

games

game_id | game_name
-------------------
1         Tennis
2         Cricket
3         Rugby

gamePlayerRel

game_id | player_id
-------------------
1         2
1         3
2         3
3         2
3         3

I want a query that will return the players id and name as well as the games that they play. If they play no games - as in the case of Tom (1) - then I want the id and name and a null or 0 value.

Desired Result

player_id | player_name | game_id | game_name
---------------------------------------------
1           Tom           null      null
2           Dick          1         Tennis
2           Dick          3         Rugby
3           Harry         1         Tennis
3           Harry         2         Cricket
3           Harry         3         Rugby

The closest I can get is with the following query:

SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
INNER JOIN gamePlayerRel
INNER JOIN games
ON players.player_id = gamePlayerRel.player_id
AND gamePlayerRel.game_id=games.game_id

This gets close except that it does not return data for players with games assigned to them. In the above examples the result is as I want except that Tom (1) with his null values is left out.

I'm a super noob at this so if I'm coming at it from the wrong angle please say so and if you can suggest a query that will do what I'm after you would make my day.

Thanks in advance for any help and advice.

To return the result set as you've shown you need to actually do two outer joins

SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
    LEFT OUTER JOIN gamePlayerRel ON players.player_id = gamePlayerRel.player_id
    LEFT OUTER JOIN games ON gamePlayerRel.game_id=games.game_id

In your case this should work just fine, however, what I really think you're trying to do is an inner join between games and gamePlayerRel and then a Left Outer Join between that virtual table and the players table. You can accomplish that via something like this:

SELECT players.player_id, players.player_name, playerGames.game_id,      playerGames.game_name
FROM players
    LEFT OUTER JOIN (Select gameplayerRel.player_id, games.game_id, games.game_name  from games inner join gamePlayerRel on games.game_id = gamePlayerRel.game_id) playerGames
       on players.player_id = playerGames.player_id

In your case you'd never need this alternative syntax, but there are some times when things can get messed up because the two left outer joins way is not exactly logically equivalent.

Here is a SQL Fiddle showing the results of the queries

I know you're using mysql, but this article does a good job of explaining the nuances of the joins, but it is written for MSSQL, although it should apply to you just the same. http://weblogs.sqlteam.com/jeffs/archive/2007/10/11/mixing-inner-outer-joins-sql.aspx

This should do the trick

SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
    INNER JOIN gamePlayerRel ON players.player_id = gamePlayerRel.player_id
    LEFT OUTER JOIN games ON gamePlayerRel.game_id=games.game_id

You need to join each table individually and also need to use a LEFT OUTER JOIN for your games table. This will pull in at least one record for every match in the players/gamePlayerRel tables. If there isn't a match you'll be returned a NULL value.

After being nudged in the right direction by the helpful folk of SO I have got a query that does what I am after though I am still not 100% sure why it works.

SELECT players.player_id, players.player_name, gamePlayerRel.game_id, games.game_name
FROM players
INNER JOIN gamePlayerRel ON players.player_id = gamePlayerRel.player_id
LEFT OUTER JOIN games ON gamePlayerRel.game_id=games.game_id

Thanks to those who commented. Once again this site proves one of the most useful I have ever found :)

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM