2011-06-24 87 views
0

在SO上MySQL似乎並不缺少層級數據問題,但它似乎主要是在管理數據庫中的這些數據或實際檢索遞歸分層數據。我的情況既不是。我有一個需要顯示的項目網格。每個項目也可以有0個或更多與其關聯的評論。現在,物品以及其數據都會顯示在網格中以及屬於該物品的任何評論中。通常需要進行某種深入查看,對話或其他用戶操作來查看網格項的子數據,但在這種情況下,我們在同一個網格中顯示父數據和子數據。可能不符合事實上的標準,但它就是這樣。從MySQL中檢索兩級分層數據的最佳方法

現在,通過單獨的MySQL查詢爲網格中的每個父項目檢索評論。我立刻就會注意到,所有完全獨立的數據庫查詢都必須針對單頁加載運行。我還沒有分析,但如果這是我們有時看到的緩慢頁面加載的一部分,我不會感到驚訝。我希望理想情況下可以將這個問題帶入單個查詢或2個。但是,我很難想出一個比目前正在做的更好的解決方案。

我的第一個想法是用某種分隔符(如'|')將每行的註釋兒童弄平。然後在渲染頁面時將它們在PHP中展開。這個問題變得越來越複雜,因爲必須將註釋中的每個字段分開,然後逐個註釋,然後考慮數據中分隔符的可能性。只是覺得維護和調試一團糟。

我的下一個想法是留下外部聯接的項目的意見,並只是在PHP項目重複帳戶。我正在使用Codeigniter的數據庫庫,它返回一個用於數據庫數據的PHP數組。這聽起來像是結果數組中可能存在大量重複的數據,可能會導致對更大的結果集進行系統評估。我在大多數情況下都認爲它不會太壞,儘管這個選項目前在我的可能性列表的頂部。理想情況下,如果我正確理解MVC,我應該儘可能將我的數據庫,業務邏輯和視圖/顯示保持分離。因此,理想情況下,模型返回的數據中不應該有任何數據庫「怪癖」(缺少更好的詞)。也就是說,無論從這個模型方法中調用數據,都不應該關注像這樣的重複數據。所以我不得不添加一個額外的循環以某種方式消除重複的項目數組條目,但只有在我已經檢索到所有的子註釋並將它們放入它們自己的數組之後。

兩個查詢是另一個想法,但我必須在SQL語句中傳遞多個項目ID以進行註釋,然後通過PHP手動壓縮所有數據。

我的目標不是擺脫在這裏做的工作,但我希望有一些更好的(資源密集程度較低,對編碼器不太混亂)的方法,我還沒有想到。

回答

2

正如您在您的問題中所述,使用聯接會帶來很多重複信息。它應該很簡單,可以在PHP中刪除,但爲什麼要將它恢復到原來的位置?

編譯SQL查詢語句時,查詢中檢索到的ID列表不應該是一個問題(請參閱cwallenpoole's答案)。或者,您可以創建一個子查詢,以便MySQL爲您重新創建ID列表 - 這取決於子查詢的密集程度。

選擇項:

SELECT * FROM item WHERE description = 'Item 1'; 

然後選擇註釋這些項目:

SELECT * FROM comment WHERE item_id IN (
    SELECT id FROM item WHERE description = 'Item 1' 
); 
2

在大多數情況下,我解決這類問題使用某種ORM Lazy-Loading system,但它不看起來像是你的選擇。

你有沒有考慮:

  1. 選擇所有頂級項目。
  2. 通過頂層集合中的ID選擇所有二級項目。
  3. 將在2中檢索到的對象與在PHP中找到的1中的項關聯起來。

基本上(在僞代碼)

$stmt = $pdo->query("SELECT ID /*columns*/ FROM ENTRIES"); 
$entries = array(); 
foreach($row as $stmt->fetchAll(PDO::FETCH_ASSOC)) 
{ 
    $row['child-entities'] = array(); 
    $entries[$row['id']] = $row; 
} 

$ids = implode(',',array_keys($entries)); 
$stmt = $pdo->query("SELECT PARENT_ID /*columns*/ FROM children WHERE PARENT_ID IN ($ids)"); 

foreach($row as $stmt->fetchAll(PDO::FETCH_ASSOC)) 
{ 
    $entries[$row['parent_pid']]['child-entities'][] = $row; 
} 

$entries現在將關聯數組與直接與子項關聯的父項。除非需要遞歸,否則這應該是兩個查詢中的所有內容。

相關問題