使用三个表和一些空值的 SQL 连接查询

pop*_*rap 1 php mysql

我正在使用 PHP 查询 mySQL 数据库中的三个表:

玩家

player_id | player_name
-----------------------
1           Tom
2           Dick
3           Harry
Run Code Online (Sandbox Code Playgroud)

游戏

game_id | game_name
-------------------
1         Tennis
2         Cricket
3         Rugby
Run Code Online (Sandbox Code Playgroud)

玩家关系

game_id | player_id
-------------------
1         2
1         3
2         3
3         2
3         3
Run Code Online (Sandbox Code Playgroud)

我想要一个返回玩家 ID 和姓名以及他们玩的游戏的查询。如果他们不玩游戏 - 就像汤姆 (1) 的情况一样 - 那么我想要 id 和名称以及 anull0值。

期望的结果

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
Run Code Online (Sandbox Code Playgroud)

我能得到的最接近的是以下查询:

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
Run Code Online (Sandbox Code Playgroud)

这很接近,只是它不会返回分配给他们的游戏的玩家的数据。在上面的示例中,结果如我所愿,只是null省略了 Tom (1) 及其值。

我在这方面是个超级菜鸟,所以如果我从错误的角度来看这个问题,请说出来,如果你能建议一个查询来完成我想要的事情,你会很开心。

预先感谢您的任何帮助和建议。

ris*_*igh 5

要返回所示的结果集,您实际上需要执行两个外连接

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
Run Code Online (Sandbox Code Playgroud)

在你的情况下,这应该工作得很好,但是,我真正认为你想做的是游戏和 gamePlayerRel 之间的内部连接,然后是虚拟表和玩家表之间的左外连接。你可以通过这样的事情来实现:

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
Run Code Online (Sandbox Code Playgroud)

在您的情况下,您永远不需要这种替代语法,但有时事情可能会变得混乱,因为两个左外连接方式在逻辑上并不完全等效。

这是一个显示查询结果的 SQL Fiddle

我知道您正在使用 mysql,但本文很好地解释了联接的细微差别,但它是为 MSSQL 编写的,尽管它应该同样适用于您。 http://weblogs.sqlteam.com/jeffs/archive/2007/10/11/mixing-inner-outer-joins-sql.aspx