2011-11-01 54 views
12

我有一張表People。我想顯示一個由每個父母組成的HTML表格,並且他們的所有孩子都在其下面。顯示每個父母的所有子女

_________ 
|People |_____________________________________________ 
|-------------------------------------------------------| 
| id  | parent | firstname  | lastname   | 
|-------------------------------------------------------| 
| 1  0  James   Donovan    | 
| 2  0  Jeffrey   Williams   | 
| 3  0  Emmit   Herring    | 
| 4  2  Carol   Williams   | 
| 5  2  Sarah   Williams   | 
| 6  1  Nikolai   Donovan    | 
|_______________________________________________________| 

預期輸出:

________________________________________________ 
|Jeffrey Williams        | 
|------------------------------------------------| 
| - Carol Williams        | 
| - Sarah Williams        | 
|________________________________________________| 
|James Donovan         | 
|------------------------------------------------| 
| - Nikolai Donovan        | 
|________________________________________________| 
|Emmit Herring         | 
|------------------------------------------------| 
|________________________________________________| 

如何建立一個包含正確的結果集遍歷關聯數組?我對正確的SQL和正確的PHP構建最終數組感到困惑。

具體而言,我不確定如何顯示兩個MySQL表之間的層次關係。就我所知,SQL結果集並不是多維的。在for循環中放入SQL查詢對於性能來說很糟糕。所以你會怎麼做?

我想我正在尋找一個在MySQL中的鄰接表實現。

這個問題應該很容易,如果我可以將所有東西都分成兩個表格,但不幸的是我必須堅持使用這種非正常的表格結構。

+0

你可以使用jquery嗎? – defau1t

+0

爲什麼我必須使用jQuery來顯示每個父項的子項一樣簡單的內容?這裏沒有PHP解決方案嗎? –

+0

@Mark我想我的問題還不夠清楚。我不是爲了幫助家庭作業。我更新了這個問題。 –

回答

13

有幾種方法可以做到這一點:

最明顯的一個是先獲取所有家長的名單,然後運行每個家長在孩子們一個單獨的查詢循環。你說這對於性能來說是「糟糕的」,但它確實不應該是這樣的,假設你有一個parent列的索引,並且你的MySQL服務器不在這個星球的另一邊。


2.如果你真的想這樣做,這是在一個單一的查詢,可以在桌子上使用LEFT JOIN自相:

SELECT 
    p.id AS parent_id, 
    p.firstname AS parent_firstname, 
    p.lastname AS parent_lastname, 
    c.id AS child_id, 
    c.firstname AS child_firstname, 
    c.lastname AS child_lastname 
FROM 
    People AS p 
    LEFT JOIN People AS c ON c.parent = p.id 
WHERE p.parent = 0 
ORDER BY p.id 

同樣,你真的,真的需要parent列的索引。 ORDER BY條款是爲了確保每個父母的孩子一起排序;你可以改變它,例如如p.lastname, p.firstname, p.id, c.lastname, c.firstname, c.id如果你想按字母順序排序的名稱。在PHP中,你則需要循環的結果並打印新的頭每當父ID的變化(記住處理,其中child_*列是空的情況下)喜歡的東西:

$res = mysql_query($sql); 
$last_parent_id = 0; 
while ($row = mysql_fetch_object($res)) { 
    if ($row->parent_id != $last_parent_id) { 
     // print parent header 
     $last_parent_id = $row->parent_id; 
    } 
    if ($row->child_id) { 
     // print child row 
    } 
} 

3。第三個選項是隻獲取所有的行用一個簡單的SELECT * FROM People查詢和PHP構建樹:

$res = mysql_query("SELECT * FROM People"); // add WHERE clauses if needed 
$names = array(); 
$parents = array(); 
$children = array(); 

while ($row = mysql_fetch_object($res)) { 
    $names[ $row->id ] = array($row->firstname, $row->lastname); 
    if ($row->parent == 0) { 
     $parents[] = $row->id; 
    } else { 
     if (!array_key_exists($row->parent, $children)) 
      $children[ $row->parent ] = array(); 
     $children[ $row->parent ][] = $row->id; 
    } 
} 

foreach ($parents as $parent_id) { 
    // print parent header 
    if (array_key_exists($parent_id, $children)) { 
     foreach ($children[ $parent_id ] as $child_id) { 
      // print child row 
     } 
    } 
} 

詩篇。如果您實際上不想在表中顯示父母和子女,但只是屬於一個家庭的父母和子女,那麼您仍然應該嘗試在SQL中進行過濾以避免獲取太多記錄。

0

爲什麼不在JavaScript中創建多線陣列?之後,只需循環訪問數組即可在DOM中獲得結果。

+1

因爲網站用戶不應該被要求啓用Javascript。爲什麼不顯示父 - >子關係列表而不訴諸用JavaScript來操縱DOM?我使用PHP和MySQL。 –

1

你可以在一個循環中使用一個循環:

$res = mysql_query("SELECT PARENT"); 
while($row = mysql_fetch_assoc($res)) 
{ 

    // echo parent 

    $res2 = mysql_query("SELECT CHILD WHERE PARENT SOMETHING"); 
    while($row2 = mysql_fetch_assoc($res2)) 
    { 

    // echo child 
    } 
} 

或者,保持它後,並存儲一個標誌。

$people = array(); 

$res = mysql_query("SELECT PARENT"); 
while($row = mysql_fetch_assoc($res)) 
{ 
    $people[] = array('is_parent' => true, 
        'info'  => $row); 

    $res2 = mysql_query("SELECT CHILD WHERE PARENT SOMETHING"); 
    while($row2 = mysql_fetch_assoc($res2)) 
    {  
    $people[] = array('is_parent' => false, 
         'info'  => $row2); 
    } 
} 

// later 

foreach($people as $person) 
{ 
    if($person['is_parent']) 
    { 
    // echo parent 
    } 
    else 
    { 
    // echo child 
    } 
} 
+0

當然,你可以,但正如我在我的問題中提到的那樣,這樣做會隨着表的增長而導致無法接受的性能問題。 –

2

根據傳統的方法,我認爲從SQL開始,連接表(即使在這種情況下左表和右表也是相同的),可能是一個很好的起點。

這主要是因爲使用RDBMS時,您必須始終處理表格結構,並以保證數據一致性的方式連接表。

所以,開始的東西,如:

SELECT 
     a.id parent_id, a.firstname parent_name, a.lastname parent_lastname, 
     b.id child_id, b.firstname child_firstname, b.lastname child_lastname 
FROM 
     People a LEFT OUTER JOIN People b ON a.id = b.parent 
WHERE 
     a.parent = 0; 

其次,你應該更喜歡使用「fetch_all」戰略(與mysqli PHP擴展,例如,但它可與PDO也),這將給你只需一次操作即可將整個結果集提取到一個二維關聯數組中。

此時你可以選擇你的路徑。

All-PHP:您可以使用PHP遍歷數組,並直接構建演示文稿標記以顯示按需組織的數據,echo將html字符串指向瀏覽器。

AJAX:if - 例如 - 你的PHP腳本已經被AJAX調用了,你也可以走查詢結果數組,但是這次解釋它構建了一個JSON結構,你可以響應這個調用,這樣的:

{ 
    "1": { 
     "id": 1, 
     "firstname": "James", 
     "lastname": "Donovan", 
     "children": { 
      "6": { 
       "id": 6, 
       "firstname": "Nikolai", 
       "lastname": "Donovan" 
      } 
     } 
    }, 
    "2": { 
     "id": 2, 
     "firstname": "Jeffrey", 
     "lastname": "Williams", 
     "children": { 
      "4": { 
       "id": 4, 
       "firstname": "Carol", 
       "lastname": "Williams" 
      }, 
      "5": { 
       "id": 5, 
       "firstname": "Sarah", 
       "lastname": "Williams" 
      } 
     } 
    }, 
    "3": { 
     "id": 3, 
     "firstname": "Emmit", 
     "lastname": "Herring", 
     "children": { } 
    } 
} 

這樣的表示將進行數據交換更好,因爲你的客戶端JavaScript可以無縫地識別它,並走到它來填充一個預先存在的空表骨架。當然,你可以直接將PHP的結果數組轉換爲json_encode()結果數組,而不是將其重構爲其他類似的東西,但是你會發現自己的東西比你已經擁有的穩定的記錄集類似的數組表示方式要差得多。

最後,all-mysql解決方案是準備一個存儲過程,有目的地構造你正在尋找的數據結構,例如,每個家庭1行,父母全名作爲第一列,子女全名作爲後續列(如果沒有子女,如Emmit Herring,則爲空欄)。

您可以再次使用PHP對結果集進行「fetch_all」,然後遍歷數組,然後完成。所以如果性能是一個問題,最後一種方法應該保證你獲得最好的結果,即使必須說服務器在計算負載和內存佔用方面支付了價格,如果你打算處理大量的數據。