2010-07-13 40 views
0

我很難過。根據Mysql和PDO中其他表的結果從表中選擇行

我有一個表項目與字段:ID,標題,created_by,組

我也有與田組的另一個表:ID,CREATED_BY,組名
與領域最終表的用戶:ID,用戶名,密碼等

想法是隻有登錄用戶創建的項目或登錄用戶是項目用戶組的一部分的項目才能被該用戶看到。

每個用戶可以是未指定數量的組的一部分,每個組可以包含未指定數量的用戶。

我現在可以想到做到這一點的唯一方法是爲每個用戶提供一個單獨的表(列出他們所屬的所有組)。

然後,我首先在項目表中搜索登錄用戶創建的項目。其次,搜索該用戶的「groups」表以找到它們所屬的每個組的ID,然後再次遞歸搜索項目表並加載當前找到的group_id與項目的組ID相匹配的每個項目。

我知道這將工作,如果編碼正確的少數項目,組和/或用戶,但我懷疑每個頁面將花費很長時間來加載/處理較大的表。對於每個用戶都有一張新表,因爲您可以擁有數千個用戶,因此可以有數千個表。

我懷疑表連接可能會提供解決方案,但我現在看不到如何。如果是這種情況,我很樂意重命名錶格字段來實現這一點。

我對檢索項目當前的代碼是這樣的(我知道這可能不是理想的):

$query = "SELECT * FROM items WHERE user_id=:u_id"; 
$stmt = $conn->prepare($query); 
$stmt->execute(array(':u_id'=>$_SESSION['u_id'])); 
$exist = '<option></option>'; 
while($uRow = $stmt->fetch()) { 
    $exist .= '<option value="'.$uRow['id'].'">'.$uRow['title'].'</option>'; 
} 
$user_groups_tbl = "user_groups_".$_SESSION['u_id']; 
$query1 = "SELECT * FROM $user_groups_tbl"; 
$query2 = "SELECT * FROM items WHERE group_id=:group"; 
$stmt1 = $conn->prepare($query1); 
$stmt2 = $conn->prepare($query2); 
$stmt1->execute(); 
while($gRow = $stmt1->fetch()) {  
    $stmt2->execute(array(':group'=>$gRow['group_id'])); 
    while($row = $stmt2->fetch()) { 
     if($row['user_id'] !== $_SESSION['u_id']) { 
      $exist .= '<option value="'.$uRow['id'].'">'.$uRow['title'].'</option>'; 
     } 
    } 
} 
return $exist; 

我希望我的需要和意圖是明確的。任何幫助,將不勝感激。

回答

3

我現在想到做這件事的唯一方法是爲每個用戶都有一個單獨的表(列出他們所屬的所有組)。

Yikes!不要這樣做!讓我們使用一些規範化來重新創建您的表格。

-- Our users 
CREATE TABLE users (
    user_id INTEGER PRIMARY KEY, 
    ... 
); 

-- And our groups 
CREATE TABLE groups (
    group_id INTEGER PRIMARY KEY, 
    ... 
); 

-- New! A list of all groups and the users that belong to them. 
-- This is also conveniently a list of users and the groups that they belong to. 
CREATE TABLE group_users (
    user_id INTEGER REFERENCES users(user_id), 
    group_id INTEGER REFERENCES groups(group_id), 
    UNIQUE KEY(user_id, group_id) 
); 

-- Finally, our mysterious "items" 
CREATE TABLE items (
    item_id ..., 
    title ..., 
    user_id INTEGER REFERENCES users(user_id), 
    group_id INTEGER REFERENCES groups(group_id) 
); 

考慮:

的想法是,只有登錄用戶或項目創建的項目,其中已登錄的用戶是該項目的用戶組的成員可以通過該用戶看到。

SELECT * 
    FROM items 
WHERE items.user_id = ? 
    OR items.group_id IN(
      SELECT group_id 
      FROM group_users 
      WHERE user_id = ? 
     ) 

這應該抓住由用戶創建的所有項目,也屬於該用戶屬於一個組的所有項目。 (注意:根據您的MySQL版本,此查詢可能無法正確優化。您可能需要將WHERE子句中的子查詢轉換爲FROM子句。)

+0

基本上相同,我的答案,但expmained更漂亮。 – thomasfedb 2010-07-13 01:31:44

+0

內容豐富,讓我大笑!我知道我錯過了一些簡單的事情!謝謝! – drent 2010-07-13 08:02:09

1

您正在尋找的關係(我認爲)稱爲has-and-belong-to-many或HABTM。您將需要具有feilds user_id和group_id的數據透視表。

然後如果你有一個用戶,你可以找到user_id所關聯的所有group_id。然後你可以使用它來查找項目。

2

嘿德倫特,這是一個很好的問題。正如你所提到的,處理多對多關係(許多用戶到很多組)的標準方法是使用連接表。下面是表:

  • 項目:ID,標題,CREATED_BY,GROUP_ID
  • :ID,CREATED_BY,組名
  • 用戶:ID,用戶名,密碼等
  • ,只是一個新的表 - users_groups:USER_ID,GROUP_ID

現在,無論何時用戶加入一個組,只需將一行添加到user_group表。例如,如果用戶327加入羣14:

INSERT INTO users_groups SET user_ID=327, group_ID=14; 

要列出所有用戶可以訪問的項目:

SELECT * FROM items 
JOIN users_groups ON users_groups.group_ID = items.group_ID 
WHERE users_groups.user_ID = :user 

確保與當前用戶的用戶ID替換:user。另外,我可能沒有使用與表格中完全相同的列名,因此請注意。

要列出用戶是其成員組:

SELECT * FROM groups 
JOIN users_groups ON users_groups.group_ID = groups.ID 
WHERE users_groups.user_ID = :user 
+0

謝謝,這也是非常有用的! – drent 2010-07-16 20:58:12

相關問題