【问题标题】:Querying a database with a one to many relationship查询具有一对多关系的数据库
【发布时间】:2019-08-31 07:58:30
【问题描述】:

我正在创建一个数据库,当用户注册时,他们会选择 3 个他们想玩的游戏。游戏存储在与用户信息表(个人信息)不同的表(游戏信息)中。我正在查询显示的第一个游戏,但我希望为每个用户显示所有三个游戏。我将如何实现显示所有游戏?

我尝试为每个游戏创建不同的变量,但这似乎并没有像我预期的那样工作并且失败了。存储在个人信息表中的游戏存储为 1 或 2 之类的数字。这些数字与 gameinfo 表相关联,并且是每个游戏的主键。

数据库结构
https://imgur.com/a/qee9C1t

    $conn = mysqli_connect('localhost', 'root', '', 'esportclub');
    $sql = "SELECT user_ID, username, Email, Gender, firstName, lastName, gameName FROM personalinformation, gameinfo WHERE game_id = firstGame";
    $result = mysqli_query ($conn, $sql);


    if (mysqli_num_rows($result) > 0) {
      echo "<table>";

      while($row = mysqli_fetch_assoc($result)) {
        echo " <tr><td> Name: ". $row{"username"}. " </td><td> Email: ". $row{"Email"}.  " </td><td> Gender: ". $row{"Gender"}. "</td>" .
          "<td> First Name: ". $row{"firstName"}. " </td><td> First Game: ". $row{"gameName"}. "</td><td> Last Name: ". $row{"lastName"}. "</td>" . "</td></tr>" ;
      }
      echo "</table>";
    } 
    else{
      echo "0 results";
    }
    $conn->close();

【问题讨论】:

  • 我们可以看看你的数据库结构吗?这似乎是"many-to-many` relationship。我会使用参考表通过存储user_ID 和game_id 对来关联用户和游戏。然后 JOIN 相应地把这些表放在一起。
  • 我添加了一个指向 imgur 帖子的链接,其中包含我的数据库截图。我也意识到这种关系是多对多的关系。
  • 您需要加入 FirstGame、SecondGame 和 ThirdGame 才能获得全部 3 个。另一种选择是将 User_ID 放入 gameinfo 表中并加入 User_ID,或者执行类似 @ 的操作showdev 说。

标签: php sql


【解决方案1】:

正如我在评论中提到的,我将创建一个表来通过存储 user_ID 和 game_id 值的唯一对来关联用户和游戏。然后我会相应地把这些表连接在一起。

但是,我看到您在personalinformation 表中为每个用户存储了三个游戏值,分别位于名为firstGame、secondGame 和thirdGame 的列中。

在这种情况下,您可以将游戏表加入其中的每一列。
因此,使用您现有的结构:

SELECT
    p.*,
    game1.`gameName` as `firstGame_name`,
    game2.`gameName` as `secondGame_name`,
    game3.`gameName` as `thirdGame_name`
FROM `personalinformation` p
LEFT JOIN `games` as game1 ON (game1.`game_id` = p.`firstGame`)
LEFT JOIN `games` as game2 ON (game2.`game_id` = p.`secondGame`)
LEFT JOIN `games` as game3 ON (game3.`game_id` = p.`thirdGame`)
WHERE 1; // or WHERE p.`user_ID` = :user_ID;

编辑

由于许多用户可以拥有一个游戏,一个用户可以拥有许多游戏,这听起来像是“多对多”的关系。

这是我对这种关系的首选方法。一个优点是您不需要限制分配的游戏数量。也就是说,用户可以拥有任意数量的游戏。

创建第三个表来存储唯一的用户/游戏对。
它会告诉您哪些游戏分配给了哪些用户。
比如:

CREATE TABLE `user_game` (
  `user_id` MEDIUMINT NOT NULL ,
  `game_id` MEDIUMINT NOT NULL
);
ALTER TABLE `user_game`
  ADD UNIQUE `unique pair` (`user_id`, `game_id`);

然后将三个表连接在一起:

SELECT
    u.*,
    g.`game_id`,
    g.`gameName`
FROM `personalinformation` u
LEFT JOIN `user_game` as ug ON ( ug.`user_id` = u.`user_ID` )
LEFT JOIN `games` as g ON ( g.`game_id` = ug.`game_id` )
WHERE 1;

您将为每个用户/游戏关系取回一行。
如果一个用户玩了三场游戏,则该用户将在结果中显示三行,每行包含一个gameName。

例如:

Name   Game
----   -----------------
Jane   League of Legends
Jane   Minecraft
Fred   Dota 2
Alex   Minecraft
Alex   War Dragons
Alex   Fortnite

更复杂的显示可能需要一些处理:

<?php

$users = array();

while($row= mysqli_fetch_object($result)) {

    $uid = $row->user_ID;

    // if this user isn't in the array...
    if (!array_key_exists($uid,$users)) {

        // ... create a user entry ...
        $user = new stdClass();
        $user->firstname = $row->firstName;

        // ... and add it to the user array.
        $users[$uid] = $user;

    }

    // if this row has a valid game ...
    if (!empty($row->game_id)) {

        // ... create a game entry ...
        $game = new stdClass();
        $game->id = $row->game_id;
        $game->name = $row->gameName;

        //.. and add the game to the user's entry
        $users[$uid]->games[$game->id]=$game;

    }

}

对于这样的结构:

Array
(
    [1] => stdClass Object
        (
            [firstname] => Jane
            [games] => Array
                (
                    [1] => stdClass Object
                        (
                            [id] => 1
                            [name] => Leage of Legends
                        )

                    [2] => stdClass Object
                        (
                            [id] => 2
                            [name] => Minecraft
                        )

                )

        )

    [2] => stdClass Object
        (
            [firstname] => Fred
            [games] => Array
                (
                    [3] => stdClass Object
                        (
                            [id] => 3
                            [name] => Dota 2
                        )

                )

        )

    [3] => stdClass Object
        (
            [firstname] => Alex
            [games] => Array
                (
                    [2] => stdClass Object
                        (
                            [id] => 2
                            [name] => Minecraft
                        )

                    [4] => stdClass Object
                        (
                            [id] => 4
                            [name] => War Dragons
                        )

                    [5] => stdClass Object
                        (
                            [id] => 5
                            [name] => Fortnite
                        )

                )

        )

)

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2022-01-10
    • 2023-03-14
    • 1970-01-01
    • 1970-01-01
    • 2021-10-21
    • 1970-01-01
    相关资源
    最近更新 更多