【问题标题】:MySQL Query Multiple ID'sMySQL查询多个ID
【发布时间】:2020-12-29 22:47:38
【问题描述】:

我已经构建了一个会员应用程序,它允许用户组合项目,其内容包含在 2 个表(“项目”和“笔记”)中。每个成员都可以根据需要创建、更新或删除任意数量的项目。

到目前为止还不错...

我希望成员能够与他们选择的其他成员分享他们的项目。在这一点上,我已经构建了一个功能,允许成员 A 输入电子邮件地址以共享项目(例如,成员 B)。如果该电子邮件存在于数据库中,它会使用项目所有者的 ID(成员 A)、“shared_with”成员的 ID(成员 B)和项目 ID 更新第三个表“共享”。 (也许我走错方向了?)

问题:我如何查询数据库以向成员 B 显示他们自己的所有项目以及与他们共享的任何项目?下面的查询说明了我一直没有用的方向。我想说,“从 user_id = (me) 的项目中选择所有项目,以及我的 ID 在 'shared_with' 列下的 'sharing' 表中的所有相应项目。......哦,是的,按顺序获取该 project_id了解您正在进行的项目。”

我的大脑是糊状的。任何方向将不胜感激。

function find_all_projects($id) {
  global $db;

  $sql = "
  SELECT * 
    FROM projects 
    LEFT 
    JOIN sharing 
      on projects.id = sharing.project_id 
   WHERE user_id = '" . db_escape($db, $id) . "' 
      OR sharing.shared_with = '" . db_escape($db, $id) . "' 
   ORDER 
      BY project_name
 ";

  $result = mysqli_query($db, $sql);
  confirm_result_set($result);  
  return $result;  
}

【问题讨论】:

  • 您应该考虑使用参数化的prepared statements,而不是像这样手动转义并将用户数据注入到查询中。
  • 我认为该表必须不只是共享,而是完全可用。并且项目与任何人(共享该项目的所有者和用户)之间的关系将在其中提及。在这样的方案中,项目选择的过程很容易。所有者由项目表中的相应列检测。
  • 如果是我,我会暂时忘记所有非 sql 的东西,而是专注于查询

标签: php mysql mysqli


【解决方案1】:

当前表结构

根据您的问题,我认为您当前的表结构类似于以下内容:

TABLE: user                 TABLE: project                                  TABLE: shared

id | email              | | id | user_id | content                      | | id | user_id | project_id
---+--------------------    ---+---------+------------------------------    ---+---------+------------
1  | james@website.com  | | 1  | 1       | Project for James            | | 9  | 1       | 5
2  | hannah@website.com | | 2  | 1       | Some other project for James | | 10 | 3       | 5
3  | lucy@website.com   | | 3  | 2       | Project for Hannah           | | 11 | 1       | 8
   |                    | | 4  | 2       | A new project for hannah     | | 12 | 2       | 8
   |                    | | 5  | 2       | Hannah's pride and Joy       | |
   |                    | | 6  | 3       | Lucy cracking down           | |
   |                    | | 7  | 3       | Lucy's second project        | |
   |                    | | 8  | 3       | Lucy's public stuff          | |

SQL

示例:https://www.db-fiddle.com/f/6KnEsGUmy5PS42usmzyTEX/0

SELECT project.id, project.user_id AS owner_id, shared.user_id AS shared_id, project.content
FROM project
    LEFT JOIN shared
        ON project.id = shared.project_id
            AND project.user_id <> ?
WHERE project.user_id = ?
    OR shared.user_id = ?;

注意

此 SQL 语句与您问题中的语句之间的主要区别是

AND project.user_id <> ?

如果ON 子句中没有该条件,您将获得该用户的每个共享项目的重复记录。 IE。如果用户与 20 个用户共享项目,则将有 20 个重复项。

这是预期的行为,如下所述:PHP while statement echoes duplicates

PHP

$sql   = "
    SELECT project.id, project.user_id AS owner_id, shared.user_id AS shared_id, project.content
    FROM project
        LEFT JOIN shared
            ON project.id = shared.project_id
                AND project.user_id <> ?
    WHERE project.user_id = ?
        OR shared.user_id = ?
";
$query = $mysqli->prepare($sql);
$query->bind_param("iii", $user_id, $user_id, $user_id);
$query->execute();

备用表结构

我建议更新您的表结构,以便拥有三个表(实际上是:usersprojectsproject_users)。然后project_user 表充当两个实体(usersprojects)之间的管道。在这种情况下,存储两者之间的关系(即所有者与共享对象)。

TABLE: user                 TABLE: project                                  TABLE: project_user

id | email              | | id | content                      | | id | user_id | project_id | role
---+--------------------    ---+------------------------------    ---+---------+------------+-----
1  | james@website.com  | | 1  | Project for James            | | 1  | 1       | 1          | 1
2  | hannah@website.com | | 2  | Some other project for James | | 2  | 1       | 2          | 1
3  | lucy@website.com   | | 3  | Project for Hannah           | | 3  | 2       | 3          | 1
   |                    | | 4  | A new project for hannah     | | 4  | 2       | 4          | 1
   |                    | | 5  | Hannah's pride and Joy       | | 5  | 2       | 5          | 1
   |                    | | 6  | Lucy cracking down           | | 6  | 3       | 6          | 1
   |                    | | 7  | Lucy's second project        | | 7  | 3       | 7          | 1
   |                    | | 8  | Lucy's public stuff          | | 8  | 3       | 8          | 1
   |                    | |    |                              | | 9  | 1       | 5          | 2
   |                    | |    |                              | | 10 | 3       | 5          | 2
   |                    | |    |                              | | 11 | 1       | 8          | 2
   |                    | |    |                              | | 12 | 2       | 8          | 2

SQL

例如:https://www.db-fiddle.com/f/imQZ6cvEEff4VgRQ4v22Qo/0

SELECT project.id, project_user.user_id, project_user.role, project.content
FROM project
    JOIN project_user
        ON project_user.project_id = project.id
WHERE project_user.user_id = ?;

PHP

$sql   = "
    SELECT project.id, project_user.user_id, project_user.role, project.content
    FROM project
        JOIN project_user
            ON project_user.project_id = project.id
    WHERE project_user.user_id = ?
";
$query = $mysqli->prepare($sql);
$query->bind_param("i", $user_id);
$query->execute();

【讨论】:

    【解决方案2】:

    您可以通过这样的表在成员和项目之间使用另一种关系:

    CREATE TABLE `project_members` (
      `project_id` INT NOT NULL,
      `member_id` INT NOT NULL,
      `is_owner` TINYINT NOT NULL DEFAULT 0,
      PRIMARY KEY (`project_id`, `member_id`));
    

    此表允许您将许多成员链接到许多项目。
    is_owner 列是一个布尔值,可以轻松查看成员是否是所有者或项目是否已共享给他。
    此外,最好将外键添加到 project_idmember_id

    【讨论】:

    • 我开始走类似的道路,但遇到了多个用户与多个用户共享多个项目的螺旋式复杂情况。
    • @LyleCrumbstorm 使用这样的连接表往往会使事情变得简单;您遇到了哪些螺旋式并发症
    • 我认为我没有完全意识到第一次通过的建议。它和你的一样,只是没有扩展的解释,对吧?
    • @LyleCrumbstorm 是的,这只是根据我的回答实现连接表。
    • @LyleCrumbstorm 您必须进行 2 次查询。一个获取所有所有者的项目,另一个获取与这些项目相关的所有用户:SELECT pm.project_id, member.* FROM member m JOIN project_members pm ON pm.member_id = m.id WHERE pm.project_id IN (list_of_owner_project_ids) AND is_owner = 0(将 list_of_owner_project_ids 替换为准备好的语句)。此外,如果您使用 PDO 而不是 mysqli,您可以拥有一个非常好的数组:phpdelusions.net/pdo/fetch_modes#FETCH_GROUP,数组的每个键都可以保存项目的 id,每个值都是与项目相关的所有用户
    猜你喜欢
    • 2014-01-26
    • 1970-01-01
    • 2021-08-20
    • 2021-04-23
    • 1970-01-01
    相关资源
    最近更新 更多