2016-04-23 21 views
3

我有一個角色需要某個證書,才能將用戶分配給該角色。SQL JOIN問題未將用戶詳細信息從查詢中帶回並將它們打印到數組中

我正在嘗試從數據庫中建立一個用戶列表,這個用戶列表中有一個或多個匹配的特定角色的證書。 (我也只查看用戶獲得的最後一個證書,並且只將該證書與該角色進行比較)

只要用戶實際上擁有該角色所需的兩個證書,該查詢就可以很好地工作。

如果用戶不匹配所有需要的證書,那麼用戶詳細信息不會回來。

  • 首先,我將說明我是運行的,以匹配用戶,則該方法我會告訴你陣列輸出結果

  • 你將看到第一個用戶(搶劫,冬青)陣列0和1匹配角色所需的兩個證書,因此所有信息(如id,圖像和名稱)都會返回到數組的第一部分。

  • 第三個用戶(daniel)數組(2)只匹配一個,所以我沒有在數組的第一部分中獲得他的名字或詳細信息。

  • 第4個用戶(katie)數組(3)不匹配,所以我在最後返回一個完全空白的數組。

  • 我需要丹尼爾和凱蒂都至少返回他們的名字和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; 
} 

和outputed陣列

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] => 
      ) 

    ) 

) 

回答

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條款它仍然沒有返回行)。


獎勵:

,並使其更有效(現在執行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[] = ... 
    } 
} 
+0

非常好的答案非常感謝你的時間。對我的代碼的其餘部分進行一些小的更改完美地工作。 –

相關問題