【问题标题】:Paginate query with multiple joins具有多个连接的分页查询
【发布时间】:2023-03-14 23:03:01
【问题描述】:

我有几个左外连接的查询,正如你在代码中看到的那样,我生成的对象包含 2 个填充有数组的对象,你知道我不能在这里使用“简单”分页,因为对于一个用户,我得到了几列(对于每个角色和每个组)例如,对于用户 1,我可以获得 4-5 个结果,因为用户可以拥有许多组和角色,我理解这是我不能在此查询中使用 LIMIT 和 offset 的主要原因,因为我会输一些信息。我的问题是,如何修改这个查询,让每页有 20 个不同的用户以及他们的所有角色和组。

$stmt = $mysqli->prepare("SELECT u.id, u.firstName, u.lastName, u.email, 
    u.phoneNumber, u.address, u.birthDate, ur.roleName, cg.id, cg.name FROM users as u 
    LEFT OUTER JOIN user_role as ur ON u.id = ur.userId 
    LEFT OUTER JOIN user_group as ug on ug.userId = u.id 
    LEFT OUTER JOIN control_group as cg on cg.id = ug.groupId WHERE u.id != ?");
$stmt->bind_param("i", $_SESSION["id"]);
$stmt->execute();
$stmt->bind_result($id, $firstName, $lastName, $email, $phoneNumber, 
    $address, $birthDate, $roleName, $groupId, $groupName);

$users = array();

while ($stmt->fetch()) {
    if (empty($users[$id])) {
        $users[$id] = array(
            'id' => $id,
            'firstName' => $firstName,
            'lastName' => $lastName,
            'email' => $email,
            'phoneNumber' => $phoneNumber,
            'address' => $address,
            'birthDate' => $birthDate,
            'roles' => array(),
            'groups' => array()
        );
    }
    if ($roleName) {
        $found = false;
        foreach ($users[$id]['roles'] as $role) {
            if($role['roleName'] == $roleName){
                $found = true;
                break;
            }
        }
        if($found == false)
            $users[$id]['roles'][] = array(
                'roleName' => $roleName
            );
     }

    if ($groupId) {
        $found = false;
        foreach ($users[$id]['groups'] as $group) {
            if($group['groupName'] == $groupName){
                $found = true;
                break;
            }
        }
        if($found == false)
            $users[$id]['groups'][] = array(
                'groupName' => $groupName
            );
     }
}

$res = []; 

foreach($users as $user) { 
    $res[] = $user; 
} 

$stmt->close();
$mysqli->close();
echo json_encode($res);

【问题讨论】:

  • 你可以得到一个数组中的所有结果,然后用偏移量和长度应用arrayslice
  • 这有什么意义,我仍然会在数据库中获取所有内容,我希望获得 20 个用户及其角色和组。
  • 只是因为你写了“我不能在这个查询中使用 LIMIT 和 offset 因为我会丢失一些信息”?这是什么意思
  • user 相关的表是否具有one-to-one 关联?如果是,那么您可以在查询中放置限制偏移量,但是当user 表与one-to-many 关联时,行为会发生变化,并且您可以为同一用户 id 获取多行,因为分页查询取决于如何定义了表之间的关系。
  • 用户与多对多的角色和组相关,因为用户可以有很多角色,而角色可以有很多用户。 @NishantNair 在这个现有查询上我不能使用 LIMIT 因为例如当我执行这个查询时,我将为一个用户获得多个结果,所以如果用户有 2 个组和 2 个角色,我将为一个用户获得 4 个结果,这样我不能使用 LIMIT 因为我不会得到 20 个不同的用户是正确的?我的问题是如何修改此查询以使每页返回 20 个不同的用户及其所有组和角色。

标签: php mysql join pagination


【解决方案1】:

好吧,我认为您可以采用两种查询方法。 用第一个你做分页

SELECT u.id FROM users LIMIT offset, count

第二个是你拥有的 u.id = (我认为应该是 =,而不是 != 如你所见)改为 u.i​​d IN

这样的事

$stmt = $mysqli->prepare("SELECT u.id from users u limit ?, ?");
$stmt->bind_param("1", $_SESSION["offset"]);
$stmt->bind_param("2", $_SESSION["limit"]);
$stmt->execute();
$stmt->bind_result($id);

$user_ids = array();

while ($stmt->fetch()) {
    $user_ids[] = $id;
}

$stmt2 = $mysqli->prepare("SELECT u.id, u.firstName, u.lastName, u.email, 
    u.phoneNumber, u.address, u.birthDate, ur.roleName, cg.id, cg.name FROM users as u 
    LEFT OUTER JOIN user_role as ur ON u.id = ur.userId 
    LEFT OUTER JOIN user_group as ug on ug.userId = u.id 
    LEFT OUTER JOIN control_group as cg on cg.id = ug.groupId WHERE u.id in (?)");
$stmt2->bind_param("1", implode(",", user_ids);
$stmt2->execute();
$stmt2->bind_result($id, $firstName, $lastName, $email, $phoneNumber, 
    $address, $birthDate, $roleName, $groupId, $groupName);

$users = array();

while ($stmt->fetch()) {
    ...
}

【讨论】:

  • 你能给我一些代码示例吗?
  • 我会试试这个,如果它对我有帮助,我会告诉你,谢谢你的建议!
  • $stmt2->bind_param("1", implode(",", user_ids); 那部分不起作用,知道如何绑定 id 数组吗?
  • 是的,我错过了一个右括号。但通常你绑定一个字符串(内爆使数组刺痛)
猜你喜欢
  • 1970-01-01
  • 2015-01-05
  • 2012-08-24
  • 2023-03-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-24
相关资源
最近更新 更多