2011-06-22 95 views
4

嘿,我已經環顧四周,但沒有解決這個問題的運氣。動態SQL排序幫助

我有一個帖子/評論數據庫,我無法正確地訂購。

我需要它主要通過它的ID進行排序,但是如果它的parent_id不等於它的id,它將放在它的父節點之後,並且這些子節點也會按id排序。

這是我目前的數據庫。

CREATE TABLE `questions` (
    `id` int(10) NOT NULL AUTO_INCREMENT, 
    `parent_id` int(10) NOT NULL, 
    `entry_type` varchar(8) NOT NULL, 
    `entry_content` varchar(1024) NOT NULL, 
    `entry_poster_id` varchar(10) NOT NULL, 
    `entry_status` varchar(1) NOT NULL, 
    `entry_score` varchar(10) NOT NULL, 
    `time_posted` varchar(10) NOT NULL, 
    PRIMARY KEY (`id`), 
    KEY `id` (`id`) 
) ENGINE=InnoDB DEFAULT CHARSET=latin1 AUTO_INCREMENT=7 ; 

-- 
-- Dumping data for table `questions` 
-- 

INSERT INTO `questions` VALUES(1, 1, 'question', 'How do I does SQL?', 'CodyC', '0', '2', '1308641965'); 
INSERT INTO `questions` VALUES(2, 1, 'answer', 'Easy, you eat cheese!', 'PatrickS', '0', '-4', '1308641965'); 
INSERT INTO `questions` VALUES(3, 2, 'comment', 'WTF are you on noobass?!', 'FraserK', '0', '100', '1308641965'); 
INSERT INTO `questions` VALUES(4, 1, 'answer', 'blah', '5', '0', '0', '1308642204'); 
INSERT INTO `questions` VALUES(5, 4, 'comment', 'blah2', '4', '0', '0', '1308642247'); 
INSERT INTO `questions` VALUES(6, 2, '2', '3', '3', '3', '3', '3'); 

和我目前的查詢

SELECT * 
FROM questions 
WHERE parent_id =1 
OR parent_id 
IN (
    SELECT id 
    FROM questions 
    WHERE parent_id =1 
    AND parent_id != id 
) 

如何訂購,使訂單ID到每個對象都其父後,其中ID = PARENT_ID意味着是一個基本水平,並沒有父!

在此先感謝。

弗雷澤

+0

你希望爲在這種情況下一個問題(ID = 1)ORDER BY或想顯示的所有問題嗎? –

+0

我需要得到一個具體的問題,所有的答案和評論 – FraserK

+0

請告訴我們你所尋求的ID的順序,所以我們可以測試我們的查詢。 – Bohemian

回答

-1
Simply use the "ORDER BY" clause to select the ordering you want! 

SELECT * 
    FROM questions 
    WHERE parent_id =1 
    OR parent_id 
    IN (
     SELECT id 
     FROM questions 
     WHERE parent_id =1 
     AND parent_id != id 
    ) 
    ORDER BY Parent_id , id 
+0

我知道,但那不會把孩子放在父母身後? – FraserK

+0

啊!明白你的意思!修改相應的SQL。 @ypercube似乎有正確的答案。 –

0

看起來有點與MySQL複雜,但您可以使用PHP它。使用遞歸函數。這將很容易處理。

這是來自代碼庫的功能。它只是創建一個無序列表樹。您可以修改它以滿足您的質量要求

function output_lis_pages($parentID = 0) 
{ 
    $stack = array(); //create a stack for our <li>'s 

    $arr = array(); 
    $sql = "select pageid, pagetitle, pagelink, parentid 
     from pages 
     where parentid = $parentID 
     order by orderid"; 

    $crs = mysql_query($sql); 

    if(mysql_num_rows($crs)==0) 
    { 
      // no child menu exists for this page 
      return false; 
    } 
    else 
    { 
      while($crow = mysql_fetch_array($crs)) 
      { 
       $arr [] = array(
        'pagetitle'=> stripslashes($crow["pagetitle"]), 
        'pagelink'=> $crow["pagelink"], 
        'parentid'=>$crow["parentid"], 
        'pageid'=>$crow["pageid"] 
        ); 
      } 
    } 

    foreach($arr as $a) 
    { 
      $str = ''; 
        //if the item's parent matches the parentID we're outputting... 
      if($a['parentid']==$parentID) 
      { 
       if($a['pagelink']=="") 
         $tmplink = "page.php?pageid=".$a['pageid']; 
       else 
         $tmplink = $a['pagelink']; 


       $str.='<li><a href="'.$tmplink.'">'.$a['pagetitle']."</a>"; 

       $subStr = output_lis_pages($a['pageid']); 

       if($subStr){ 
         $str.="\n".'<ul>'.$subStr.'</ul>'."\n"; 
       } 

       $str.='</li>'."\n"; 
       $stack[] = $str; 
      } 
    } 
    //If we have <li>'s return a string 
    if(count($stack)>0) 
    { 
      return join("\n",$stack); 
    } 

    //If no <li>'s in the stack, return false 
    return false; 
} 
+0

你能舉個例子嗎?遞歸和我現在不是最好的朋友... – FraserK

+0

哇,我無法理解這一切...我什至不知道它是如何相關的。 – FraserK

1

這似乎工作:

SELECT * 
FROM questions 
order by case when parent_id != id then parent_id else id end, id; 

但是這取決於你是否要孩子之前孫子等你的問題沒有明確規定。

但是,如果您使用這種技術,您可以使您的訂購期限(s)儘可能複雜 - 不需要是選定的列 - 只需填寫您所需的。

0
SELECT * 
     , CASE WHEN parent_id = 1 THEN id ELSE parent_id END AS sort_level 
    FROM questions 
    WHERE parent_id = 1 
     OR parent_id 
      IN (
       SELECT id 
       FROM questions 
       WHERE parent_id = 1 
       AND parent_id != id 
      ) 
    ORDER BY sort_level 
      , id 
0

您已經遇到了關係數據庫系統的舊bugbear。當你的數據是層次結構時,他們並不樂於與之合作。你有一個問題,試圖從數據庫記錄中產生真正的特定圖形漫步。沒有SQL方言中的遞歸功能,這很難。這裏是一個鏈接,可能會有幫助: http://explainextended.com/2009/03/17/hierarchical-queries-in-mysql/

又見,在計算器上:What are the options for storing hierarchical data in a relational database?

0

尋找到你的問題和閱讀您的評論 - 「我需要得到一個具體的問題,所有的答案和註釋」 ,我認爲你希望展示每個問題,然後是答案,然後是評論。對?

如果是這樣,這是你的查詢:

SELECT `id`, 
(CASE 
    WHEN `entry_type` = 'question' THEN CONCAT(`id`, '-', `parent_id`) 
    WHEN `entry_type` = 'answer' THEN CONCAT(`id`, '-', `parent_id`) 
    WHEN `entry_type` = 'comment' THEN CONCAT(`parent_id`, '-', `id`) 
END) `sort_order`, 
`entry_type`, `entry_content` 
FROM `questions` 
ORDER BY `sort_order`; 

上面的查詢會給你的每一個問題,其次是它的第一個答案,其次是評論它的第一個答案;然後是第二個答案,然後是對第二個答案的評論,等等。

因此,對於你給了插入,這將是輸出:

+----+------------+------------+--------------------------+ 
| id | sort_order | entry_type | entry_content   | 
+----+------------+------------+--------------------------+ 
| 1 | 1-1  | question | How do I does SQL?  | 
| 2 | 2-1  | answer  | Easy, you eat cheese! | 
| 3 | 2-3  | comment | WTF are you on noobass?! | 
| 6 | 2-6  | comment | 3      | 
| 4 | 4-1  | answer  | blah      | 
| 5 | 4-5  | comment | blah2     | 
+----+------------+------------+--------------------------+ 

希望它能幫助。

編輯:更新查詢來獲取答案和註釋,只有一個問題

SELECT `id`, 
(CASE 
    WHEN (`entry_type` IN ('question', 'answer')) THEN `id` 
    WHEN `entry_type` = 'comment' THEN `parent_id` 
END) `sort_order_1`, 
(CASE 
    WHEN (`entry_type` IN ('question', 'answer')) THEN `parent_id` 
    WHEN `entry_type` = 'comment' THEN `id` 
END) `sort_order_2`, 
(CASE 
    WHEN (`entry_type` IN ('question', 'answer')) THEN `parent_id` 
    WHEN `entry_type` = 'comment' THEN (SELECT `Q1`.`parent_id` FROM `questions` `Q1` WHERE `Q1`.`id` = `Q`.`parent_id`) 
END) `question_id`, 
`entry_type`, `entry_content` 
FROM `questions` `Q` 
HAVING `question_id` = 1 
ORDER BY `sort_order_1`, `sort_order_2`; 

OUTPUT:

+----+--------------+--------------+-------------+------------+--------------------------+ 
| id | sort_order_1 | sort_order_2 | question_id | entry_type | entry_content   | 
+----+--------------+--------------+-------------+------------+--------------------------+ 
| 1 | 1   | 1   |   1 | question | How do I does SQL?  | 
| 2 | 2   | 1   |   1 | answer  | Easy, you eat cheese! | 
| 3 | 2   | 3   |   1 | comment | WTF are you on noobass?! | 
| 6 | 2   | 6   |   1 | comment | 3      | 
| 4 | 4   | 1   |   1 | answer  | blah      | 
| 5 | 4   | 5   |   1 | comment | blah2     | 
+----+--------------+--------------+-------------+------------+--------------------------+ 

您可以更改HAVING部分來獲取特定問題的答案和評論。希望這可以幫助!

編輯2:一種可能的實現可能(但我認爲它可能有大的表一些性能問題):

SELECT `a`.`id` AS `question_id`, `a`.`entry_content` AS `question`, 
    `b`.`id` AS `answer_id`, `b`.`entry_content` AS `answer`, 
    `c`.`id` AS `comment_id`, `c`.`entry_content` AS `comment` 
FROM `questions` `a` 
LEFT JOIN `questions` `b` ON (`a`.`id` = `b`.`parent_id` AND `b`.`entry_type` = 'answer') 
LEFT JOIN `questions` `c` ON (`b`.`id` = `c`.`parent_id` AND `c`.`entry_type` = 'comment') 
WHERE `a`.`entry_type` = 'question' 
AND `a`.`id` = 1 
ORDER BY `a`.`id`, `b`.`id`, `c`.`id`; 

OUTPUT:

+----+--------------------+------+-----------------------+------+--------------------------+ 
| id | question   | id | answer    | id | comment     | 
+----+--------------------+------+-----------------------+------+--------------------------+ 
| 1 | How do I does SQL? | 2 | Easy, you eat cheese! | 3 | WTF are you on noobass?! | 
| 1 | How do I does SQL? | 2 | Easy, you eat cheese! | 6 | 3      | 
| 1 | How do I does SQL? | 4 | blah     | 5 | blah2     | 
+----+--------------------+------+-----------------------+------+--------------------------+ 
+0

「」我需要得到一個具體的問題,以及所有的答案和評論「,我認爲你希望展示每個問題後面跟着答案,然後是評論,對嗎?你明白'one'這個詞嗎? – FraserK

+0

@FraserK:請在上面的EDIT中看到新的查詢;這會給你一個具體問題的結果。我認爲你不必強調ONE,我「理解」這個詞。我們都在這裏分享的東西,答案可能並不總是確切的。我的原始查詢給了你所有的問題,我想用PHP中的一個簡單的代碼,很快就可以爲特定問題檢索答案和評論。無論如何,我希望用新的查詢,你會得到你想要的。讓我知道它是否有幫助。 – Abhay

0

嘗試一個星期後,我無法讓它與查詢一起工作,所以我決定只用PHP來完成,這也將減少MySQL引擎的負載。這是我的PHP的任何人希望引用它。

$question_id = $database->escape_string($question_id); //escape input 
$q = "SELECT * FROM questions WHERE parent_id = $question_id OR parent_id IN (SELECT id FROM questions WHERE parent_id = $question_id AND parent_id != id) ORDER BY parent_id , id"; 
$database->dbquery($q);//query the DB 
while($row = $database->result->fetch_assoc()){//Process results to standard array. 
    //other irrelevant stuff happens here 
    $unsorted[] = $row; 
} 
$question = array_shift($unsorted);//take the question off the array 
$sorted[] = $question;//add it to the start of the sorted array 
$qusetion_id = $question['id']; 
foreach($unsorted as $row){//this creates a multidimensional hierarchy of the answers->comments 
    if($row['parent_id'] == $question_id){//if its an answer 
     $sorted_multi[$row['id']] = array();//create a new answer sub-array 
     $sorted_multi[$row['id']][] = $row;//append it 
    }else{ 
     $sorted_multi[$row['parent_id']][] = $row;//append the answer to the correct sub-array 
    } 
} 
foreach($sorted_multi as $temp){//converts the multidimensional into a single dimension appending it to the sorted array. 
    foreach($temp as $row){ 
     $sorted[] = $row; 
    } 
} 

乏味的,是的,但它的工作原理進行到底,因爲那需要做後MySQL的其他不可預見的處理更好。

感謝所有的答覆雖然:) :) :)