2012-04-03 33 views
0

在儘可能少的SQL語句的文件夾ID考慮數據庫的表:文件夾獲取儘可能

 
folders 
id parent_id name 
1 0   a 
2 1   b 
3 2   c 

「B」是「A」中的文件夾,因此它的PARENT_ID是「A」的ID。
parent_id爲0的文件夾僅表示它位於根文件夾中。

我在PHP,可以幫助我得到這個我感興趣的路徑的ID寫了一個遞歸函數

例如:

echo get_folder_id('a/b/c'); // 3 (3 SQL queries) 
echo get_folder_id('a'); // 1 (1 SQL query) 
echo get_folder_id('a/b'); // 2 (2 SQL queries) 
echo get_folder_id('a/c'); // false (2 SQL queries) 

問題:對於在每個文件夾路徑,我不得不向SQL Server查詢數據庫服務器。

問題:如果路徑是'a/b/c',有沒有辦法減少查詢次數?

這是我目前的工作解決方案,供參考。

function get_folder_id($path, $parent_id=0) { 
    $path = explode('/', $path); 
    $id = 0; 

    //if there's only 1 folder in the path, query the database for the ID 
    if (count($path) == 1) { 
     $rs = $this->db->select('id') 
       ->from('folders') 
       ->where('name', $path[0]) 
       ->where('parent_id', $parent_id) 
       ->limit(1) 
       ->get(); 

     if ($rs->num_rows() == 0) return FALSE; 

     $result = $rs->row_array(); 
     return $result['id']; 
    } 

    foreach($path AS $i=>$p) { 
     if ($i==0 && $p=='') continue; //if a path starts with/move on to the next item 
     $id = $this->get_folder_id($p, $id); 
    } 

    return $id; 
} 

注意:我使用CodeIgniter框架,但這與我的問題無關。只是人們想知道爲什麼我用$這個 - > get_folder_id()和$這個 - >分貝

+0

什麼是文件夾的最大深度? – safarov 2012-04-03 09:56:22

+0

沒有最大深度。它的設計方式使您可以儘可能多地嵌套文件夾。 – wyred 2012-04-03 09:59:21

+0

您是否需要路徑中每個文件夾的每個ID? – cloakedninjas 2012-04-03 10:15:53

回答

0

我剛剛提出的一個解決方案是在同一張桌子上使用一系列的LEFT JOIN。

SELECT tb3.id FROM folders AS tb1 
LEFT JOIN folders AS tb2 ON tb2.parent_id=tb1.id 
LEFT JOIN folders AS tb3 ON tb3.parent_id=tb2.id 
WHERE tb1.name='a' AND tb2.name='b' AND tb3.name='c' 
LIMIT 1 

根據路徑中的文件夾數量,我可以動態生成上面的SQL。 我不確定這是否是完美的解決方案,但現在它按預期工作。

任何反饋意見是否這是一個好主意,非常感謝!

$path = 'a/b/c'; 
$path = explode('/', $path); 

$sql = "SELECT tb".count($path).".id FROM folders AS tb1"; 
for($x=1, $max = count($path); $x<=$max; $x++) { 
    $sql .= " LEFT JOIN folders AS tb".($i+2); 
    $sql .= " ON tb".($i+2).".parent_id = tb"($i+1).".id"; 
} 

$sql .= " WHERE 1"; 

foreach($path AS $x => $p) { 
    $sql .= " AND tb".($x=1).".name='".$p."'"; 
} 

$sql .= " LIMIT 1"; 
0

沒有爲你的問題非常簡單的解決方案:

在數據庫中創建一個遞歸存儲功能和調用它PHP。這應該是數據庫功能,因爲如果你在PHP中實現這個功能,你必須從PHP發送很多查詢。

+0

即使我在DB中創建遞歸函數,它仍然會運行「多個查詢」對嗎?我不熟悉存儲的功能。 – wyred 2012-04-03 10:29:00

+0

您將運行多個查詢,但這不是問題。問題是,如果PHP函數運行所有查詢,則發送每個查詢的請求,但是如果在存儲函數中執行此操作,則只需要一個對數據庫服務器的請求,它將運行所有隻需要一個請求的查詢結果。使用多個查詢是正常的事情,但您需要儘量減少請求的數量。 – 2012-04-03 11:31:23

+0

通過這種方式,您將發送一條命令到數據庫服務器,您將得到一個答案,您的數據庫服務器將在內部解決所有問題。 – 2012-04-03 11:32:44

相關問題