2014-01-23 77 views
0

我已經制作了一個簡單的表來了解親子關係,但我似乎沒有得到正確的結果。我想按字母順序「名稱」字段中,只有那些誰沒有父母(PARENT_ID == 0) MYSQL:選擇父級按字母順序分組的按字母順序排序的兒童

  • ,但只要有子行父,他們應打印後

    1. 第一排序呢父母也按姓名按字母順序排序。

    實施例的表:

    ===================================== =======================

    CREATE TABLE IF NOT EXISTS `test` (
        `id` int(11) NOT NULL AUTO_INCREMENT, 
        `parent_id` int(11) NOT NULL DEFAULT '0', 
        `name` varchar(255) NOT NULL, 
        PRIMARY KEY (`id`) 
    ) ENGINE=MyISAM DEFAULT CHARSET=utf8 AUTO_INCREMENT=9 ; 
    
    -- 
    -- Dumping data for table `test` 
    -- 
    
    INSERT INTO `test` (`id`, `parent_id`, `name`) VALUES 
    (1, 4, 'Zorg'), 
    (2, 0, 'Woordolack'), 
    (3, 4, 'Akriller'), 
    (4, 0, 'Metabrusher'), 
    (5, 2, 'Intersplitter'), 
    (6, 0, 'Beaverbrain'), 
    (7, 4, 'Torgeoruos'), 
    (8, 2, 'Deptezaurus'); 
    

    ==================== ========================================

    這是我想要的使用PHP輸出到Web瀏覽器:

    Beaverbrain 
    Metabrusher 
    -> Akriller 
    -> Torgeoruos 
    -> Zorg 
    Woordolack 
    -> Deptezaurus 
    -> Intersplitter 
    

    ================================================ ============

    我應該說這是一個示例表,只是爲了展示這個想法,所以可以通過任何方式修改它以獲得正確的結果。

  • 回答

    3

    你可以試試這個查詢

    SELECT IF(child = '',parent,CONCAT('->',child)) as value 
    FROM 
        (SELECT parent.name as parent,child.name as child 
        FROM test parent 
         INNER JOIN 
         (SELECT id,parent_id,name FROM test 
         UNION 
         SELECT null,id,'' FROM test 
         WHERE parent_id = 0)child 
        WHERE parent.parent_id = 0 
        AND child.parent_id = parent.id 
        ORDER BY parent,child 
        )parent_child 
    

    sqlFiddle

    什麼查詢確實是INNER JOIN試驗與測試,並找出哪些是父母和孩子。內部UNION SELECT null,id,'' FROM test WHERE parent_id = 0創建一個空的子(ren)用於顯示目的。然後,外部SELECT會查看孩子是否「打印出父母」,否則在孩子面前連接->。所以你得到你想要的結果。

    以下版本可能會快一點。由於我們只是用NULL子代創建父項,而不是使用子項作爲INNER JOIN(上圖)的一部分。

    SELECT IF(child IS NULL,parent,CONCAT('->',child)) as value 
    FROM 
    (SELECT parent.name as parent,child.name as child 
        FROM test parent 
        INNER JOIN test child ON child.parent_id = parent.id 
        WHERE parent.parent_id = 0 
        UNION 
        SELECT test.name as parent,NULL as child #This creates a NULL child row 
        FROM test WHERE test.parent_id = 0  #for parent display purpose 
        ORDER BY parent,child 
    )parent_child 
    

    sqlFiddle

    但是我會用下面的查詢,而不是和PHP內,檢查,看看是否isParent標誌是1或0,然後顯示相應的字段。

    SELECT 0 as isParent,parent.name as parent,child.name as child, 
         parent.id as parentId,child.id as childId 
        FROM test parent 
    INNER JOIN test child ON child.parent_id = parent.id 
    WHERE parent.parent_id = 0 
    UNION 
    SELECT 1 as isParent,test.name as parent,NULL as child, 
         test.id as parentId,NULL as childId 
        FROM test WHERE test.parent_id = 0  
    ORDER BY parent,child 
    

    sqlFiddle

    +0

    哇,它以某種方式工作!這是學習MYSQL的非常酷的例子(雖然我很難理解)。但是,如果真正的表有幾千條記錄,並且還要連接其他表以獲得更多數據,它將如何影響性能? – TOL

    +0

    性能明智我不確定,取決於索引,但直到您真正在實際數據上運行時纔會知道。要理解它,你可以嘗試選擇(突出顯示)內部的單個選擇並在sqlfiddle上運行它們,你會看到數據返回並且你會理解。一旦你掌握了它就很簡單。 –

    +0

    我用一個不同的版本更新了我的答案,這個版本可能會更快一些,而且更容易理解。 –

    0

    在管理層次數據,你可以用一個簡單的PHP遞歸函數代替,

    function DisplayTree($parent , $depth)  {                          
        $sql = $this->db->query("SELECT id,name FROM '$table' WHERE parent_id = '$parent'"); 
    
         foreach($sql->result() as $field) { 
         print "<fieldset style=\"margin-left:$depth%; width:300px\">"; 
          print $field->name; 
         print "</fieldset>"; 
    
         $this->DisplayTree($field->code , $depth+8);   
        } 
    
        } 
    
    0

    使用一對情侶在PHP簡單的查詢,

    $r1 = $db->query("select * from test where parent_id = 0 order by name asc") or die('err in q1'); 
        while($arr1 = $r1->fetch_assoc()){ 
          $parent = $arr1['name']; 
          $parent_id = $arr1['id']; 
          echo $parent 
          $r2 = $db->query("select * from test where parent_id = $parent order by name asc") or die('err in q2'); 
          while($arr2 = $r2->fetch_assoc()){ 
           $child = $arr2['name']; 
           echo $child."<br />"; 
          } 
        } 
    
    +0

    是的,這是簡單而明顯的方式,但我不使用它,因爲如果表中有數百個父母,則第二個查詢將執行數百次,只是爲了生成一個頁面。如果這個頁面每秒被用戶請求幾次......這會造成真正的性能問題。 – TOL

    0

    試試這個解決方案:

    SELECT 
        A.id, 
        A.name 
    FROM 
        `test` AS A LEFT JOIN `test` AS B ON A.`parent_id` = B.`id` 
    GROUP BY 
        A.`id` 
    ORDER BY 
        IFNULL(B.`name`, A.`name`), 
        COALESCE(A.`parent_id`, A.`id`), 
        A.`parent_id` != 0, 
        A.`name`;