SQL JOIN 问题无法从查询中返回用户详细信息并将其打印在数组中
SQL JOIN issue not bringing user details back from query and printing them in array
我的角色需要某些证书才能将用户分配给该角色。
我正在尝试从数据库中构建一个用户列表,这些用户具有 1 个或多个与此特定角色匹配的证书。 (我也只查看用户获得的最后一个证书,并将该证书与角色进行比较)
只要用户实际拥有该角色所需的两个证书,查询就非常有效。
如果用户不匹配所有需要的证书,则该用户的详细信息不会返回。
首先我会告诉你我运行匹配用户的方法然后我会告诉你数组输出结果
您将看到前 2 个用户(rob、holly)数组 0 和 1 匹配该角色所需的两个证书,因此他们的所有信息(如 id、图像和名称)都会在第一部分返回数组的。
第三个用户 (daniel) array(2) 只匹配一个所以我没有在数组的第一部分得到他的名字或详细信息。
第 4 个用户 (katie) 数组 (3) 不匹配所以我 return 最后一个完全空白的数组。
我需要 Daniel 和 Katie 至少 return 他们的名字和 idimage 以便我可以将它们打印到屏幕上。
我认为这与用户的 LEFT JOIN 有关,但即使我执行 RIGHT JOIN 也没有任何结果。如果我坚持 FULL JOIN 查询完全失败。
//$allcertificates contains ids of certificates required for role
public function getStaffByProjectRoleCertificates($allCertificates)
{
//get all active users
$allUsers = $this->allActiveUser();
$users = array();
$temp = 0;
//loop through the users to find matches
for($i = 0; $i < count($allUsers); $i++)
{
$allRows = array();
for($j = 0; $j < count($allCertificates); $j++)
{
$query = sprintf("
SELECT cert.certName, usercert.idusercert, usercert.usercertEnd, user.iduser, user.idimage, user.userForename, user.userSurname, certStatus.certStatusName FROM usercert
LEFT JOIN user ON user.iduser = usercert.iduser
INNER JOIN cert ON usercert.idcert = cert.idcert
INNER JOIN certStatus ON certStatus.idcertStatus = usercert.idcertStatus
WHERE
usercert.iduser=%s AND usercert.idcert=%s AND
NOT EXISTS
(SELECT * FROM `usercert` as u2 WHERE u2.iduser=%s AND u2.idcert=%s AND u2.idcert = usercert.idcert
AND u2.idusercert > usercert.idusercert)
",
$this->db->GetSQLValueString($allUsers[$i], "int"),
$this->db->GetSQLValueString($allCertificates[$j], "int"),
$this->db->GetSQLValueString($allUsers[$i], "int"),
$this->db->GetSQLValueString($allCertificates[$j], "int"));
$result = $this->db->query($this->db->link, $query) or die($this->db->error($this->db->link));
$numRows = $this->db->num_rows($result);
$row = $this->db->fetch_assoc($result);
array_push($allRows, $row);
if($numRows !=0)
{
$temp += 1;
}
if($j == count($allCertificates) -1)
{
array_push($users, array("iduser" => $row['iduser'], 'idimage'=>$row['idimage'], 'forename'=>$row['userForename'], 'surname'=>$row['userSurname'], "cert_no" => $temp, "data"=>$allRows));
$temp =0;
}
}
}
function sortByOrder($a, $b)
{
return $b['cert_no'] - $a['cert_no'];
}
usort($users, 'sortByOrder');
print_r($users);
return $users;
}
和输出数组
Array
(
[0] => Array
(
[iduser] => 90
[idimage] =>
[forename] => Holly
[surname] => Bain
[cert_no] => 2
[data] => Array
(
[0] => Array
(
[certName] => Full UK Driving License
[idusercert] => 21
[usercertEnd] => 2016-05-31
[iduser] => 90
[idimage] =>
[userForename] => Holly
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
[1] => Array
(
[certName] => test certificate
[idusercert] => 22
[usercertEnd] => 2016-05-31
[iduser] => 90
[idimage] =>
[userForename] => Holly
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
)
)
[1] => Array
(
[iduser] => 88
[idimage] => 197
[forename] => Robert
[surname] => Bain
[cert_no] => 2
[data] => Array
(
[0] => Array
(
[certName] => Full UK Driving License
[idusercert] => 24
[usercertEnd] => 2017-07-01
[iduser] => 88
[idimage] => 197
[userForename] => Robert
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
[1] => Array
(
[certName] => test certificate
[idusercert] => 19
[usercertEnd] => 2016-05-31
[iduser] => 88
[idimage] => 197
[userForename] => Robert
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
)
)
[2] => Array
(
[iduser] =>
[idimage] =>
[forename] =>
[surname] =>
[cert_no] => 1
[data] => Array
(
[0] => Array
(
[certName] => Full UK Driving License
[idusercert] => 20
[usercertEnd] => 2016-05-31
[iduser] => 86
[idimage] => 196
[userForename] => Daniel
[userSurname] => Robinson
[certStatusName] => Expiring In 2 Months
)
[1] =>
)
)
[3] => Array
(
[iduser] =>
[idimage] =>
[forename] =>
[surname] =>
[cert_no] => 0
[data] => Array
(
[0] =>
[1] =>
)
)
)
您的 SQL- 查询中有一个非常重要的逻辑错误。
稍微简化一下:
SELECT *
FROM usercert
LEFT JOIN user ON user.iduser = usercert.iduser
INNER JOIN cert ON usercert.idcert = cert.idcert
INNER JOIN certStatus ON certStatus.idcertStatus = usercert.idcertStatus
WHERE usercert.iduser=%s AND usercert.idcert=%s
据我所知,凯蒂没有任何证书。所以 usercert
中没有行,所以 LEFT JOIN
上没有任何内容,所以没有提供她的用户信息。
改成
SELECT *
FROM user
LEFT JOIN usercert
ON usercert.iduser = user.iduser
AND usercert.idcert = %s
LEFT JOIN cert ON cert.idcert = usercert.idcert AND
LEFT JOIN certStatus ON certStatus.idcertStatus = usercert.idcertStatus
WHERE user.iduser = %s
AND NOT EXISTS
(SELECT * FROM `usercert` as u2
WHERE u2.iduser = user.iduser
AND u2.idcert = cert.idcert
AND u2.idcert = usercert.idcert
AND u2.idusercert > usercert.idusercert)
因此 FROM user
以便始终包含用户数据。
并且 LEFT JOIN usercert
带有那个特定的证书(如果我们把它放在 WHERE
子句中它仍然 returns 没有行)。
奖金:
并使其更高效(您现在执行 count($allUsers) * count($allCertificates)
查询,如果您有很多用户,这些查询将加起来):
改成:
LEFT JOIN usercert
ON usercert.iduser = user.iduser
AND usercert.idcert = IN (%s, %s, %s)
[..snip..]
WHERE user.status = 'active'
AND NOT EXISTS ([..snip..])
ORDER BY user.iduser
所以您在一次查询中就拥有了所有数据。验证查询是否给出正确的结果 (phpmyadmin) 并在 PHP.
中解析它
foreach($rows as $row) {
if (same iduser as previous) {
add certificate to item in $users
} else {
$user[] = ...
}
}
我的角色需要某些证书才能将用户分配给该角色。
我正在尝试从数据库中构建一个用户列表,这些用户具有 1 个或多个与此特定角色匹配的证书。 (我也只查看用户获得的最后一个证书,并将该证书与角色进行比较)
只要用户实际拥有该角色所需的两个证书,查询就非常有效。
如果用户不匹配所有需要的证书,则该用户的详细信息不会返回。
首先我会告诉你我运行匹配用户的方法然后我会告诉你数组输出结果
您将看到前 2 个用户(rob、holly)数组 0 和 1 匹配该角色所需的两个证书,因此他们的所有信息(如 id、图像和名称)都会在第一部分返回数组的。
第三个用户 (daniel) array(2) 只匹配一个所以我没有在数组的第一部分得到他的名字或详细信息。
第 4 个用户 (katie) 数组 (3) 不匹配所以我 return 最后一个完全空白的数组。
我需要 Daniel 和 Katie 至少 return 他们的名字和 idimage 以便我可以将它们打印到屏幕上。
我认为这与用户的 LEFT JOIN 有关,但即使我执行 RIGHT JOIN 也没有任何结果。如果我坚持 FULL JOIN 查询完全失败。
//$allcertificates contains ids of certificates required for role
public function getStaffByProjectRoleCertificates($allCertificates)
{
//get all active users
$allUsers = $this->allActiveUser();
$users = array();
$temp = 0;
//loop through the users to find matches
for($i = 0; $i < count($allUsers); $i++)
{
$allRows = array();
for($j = 0; $j < count($allCertificates); $j++)
{
$query = sprintf("
SELECT cert.certName, usercert.idusercert, usercert.usercertEnd, user.iduser, user.idimage, user.userForename, user.userSurname, certStatus.certStatusName FROM usercert
LEFT JOIN user ON user.iduser = usercert.iduser
INNER JOIN cert ON usercert.idcert = cert.idcert
INNER JOIN certStatus ON certStatus.idcertStatus = usercert.idcertStatus
WHERE
usercert.iduser=%s AND usercert.idcert=%s AND
NOT EXISTS
(SELECT * FROM `usercert` as u2 WHERE u2.iduser=%s AND u2.idcert=%s AND u2.idcert = usercert.idcert
AND u2.idusercert > usercert.idusercert)
",
$this->db->GetSQLValueString($allUsers[$i], "int"),
$this->db->GetSQLValueString($allCertificates[$j], "int"),
$this->db->GetSQLValueString($allUsers[$i], "int"),
$this->db->GetSQLValueString($allCertificates[$j], "int"));
$result = $this->db->query($this->db->link, $query) or die($this->db->error($this->db->link));
$numRows = $this->db->num_rows($result);
$row = $this->db->fetch_assoc($result);
array_push($allRows, $row);
if($numRows !=0)
{
$temp += 1;
}
if($j == count($allCertificates) -1)
{
array_push($users, array("iduser" => $row['iduser'], 'idimage'=>$row['idimage'], 'forename'=>$row['userForename'], 'surname'=>$row['userSurname'], "cert_no" => $temp, "data"=>$allRows));
$temp =0;
}
}
}
function sortByOrder($a, $b)
{
return $b['cert_no'] - $a['cert_no'];
}
usort($users, 'sortByOrder');
print_r($users);
return $users;
}
和输出数组
Array
(
[0] => Array
(
[iduser] => 90
[idimage] =>
[forename] => Holly
[surname] => Bain
[cert_no] => 2
[data] => Array
(
[0] => Array
(
[certName] => Full UK Driving License
[idusercert] => 21
[usercertEnd] => 2016-05-31
[iduser] => 90
[idimage] =>
[userForename] => Holly
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
[1] => Array
(
[certName] => test certificate
[idusercert] => 22
[usercertEnd] => 2016-05-31
[iduser] => 90
[idimage] =>
[userForename] => Holly
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
)
)
[1] => Array
(
[iduser] => 88
[idimage] => 197
[forename] => Robert
[surname] => Bain
[cert_no] => 2
[data] => Array
(
[0] => Array
(
[certName] => Full UK Driving License
[idusercert] => 24
[usercertEnd] => 2017-07-01
[iduser] => 88
[idimage] => 197
[userForename] => Robert
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
[1] => Array
(
[certName] => test certificate
[idusercert] => 19
[usercertEnd] => 2016-05-31
[iduser] => 88
[idimage] => 197
[userForename] => Robert
[userSurname] => Bain
[certStatusName] => Expiring In 2 Months
)
)
)
[2] => Array
(
[iduser] =>
[idimage] =>
[forename] =>
[surname] =>
[cert_no] => 1
[data] => Array
(
[0] => Array
(
[certName] => Full UK Driving License
[idusercert] => 20
[usercertEnd] => 2016-05-31
[iduser] => 86
[idimage] => 196
[userForename] => Daniel
[userSurname] => Robinson
[certStatusName] => Expiring In 2 Months
)
[1] =>
)
)
[3] => Array
(
[iduser] =>
[idimage] =>
[forename] =>
[surname] =>
[cert_no] => 0
[data] => Array
(
[0] =>
[1] =>
)
)
)
您的 SQL- 查询中有一个非常重要的逻辑错误。 稍微简化一下:
SELECT *
FROM usercert
LEFT JOIN user ON user.iduser = usercert.iduser
INNER JOIN cert ON usercert.idcert = cert.idcert
INNER JOIN certStatus ON certStatus.idcertStatus = usercert.idcertStatus
WHERE usercert.iduser=%s AND usercert.idcert=%s
据我所知,凯蒂没有任何证书。所以 usercert
中没有行,所以 LEFT JOIN
上没有任何内容,所以没有提供她的用户信息。
改成
SELECT *
FROM user
LEFT JOIN usercert
ON usercert.iduser = user.iduser
AND usercert.idcert = %s
LEFT JOIN cert ON cert.idcert = usercert.idcert AND
LEFT JOIN certStatus ON certStatus.idcertStatus = usercert.idcertStatus
WHERE user.iduser = %s
AND NOT EXISTS
(SELECT * FROM `usercert` as u2
WHERE u2.iduser = user.iduser
AND u2.idcert = cert.idcert
AND u2.idcert = usercert.idcert
AND u2.idusercert > usercert.idusercert)
因此 FROM user
以便始终包含用户数据。
并且 LEFT JOIN usercert
带有那个特定的证书(如果我们把它放在 WHERE
子句中它仍然 returns 没有行)。
奖金:
并使其更高效(您现在执行 count($allUsers) * count($allCertificates)
查询,如果您有很多用户,这些查询将加起来):
改成:
LEFT JOIN usercert
ON usercert.iduser = user.iduser
AND usercert.idcert = IN (%s, %s, %s)
[..snip..]
WHERE user.status = 'active'
AND NOT EXISTS ([..snip..])
ORDER BY user.iduser
所以您在一次查询中就拥有了所有数据。验证查询是否给出正确的结果 (phpmyadmin) 并在 PHP.
中解析它foreach($rows as $row) {
if (same iduser as previous) {
add certificate to item in $users
} else {
$user[] = ...
}
}