2012-10-07 69 views
1

我需要一個SQL查詢以下複雜的任務......選擇和列表的孩子和家長

我需要從一個名爲parent_id列選擇。如果parent_id的行有0,這意味着它是一個類別(它也有type列,說cat類別),如果一行有1個或更多的parent_id這意味着它是一個規則。規則的parent_id是一個類別的rule_id

表結構與它的一些數據: phpMyAdmin table data

我需要的方式來選擇,即每個類別中,都有孩子在它之下。從圖片我們會得到這個:

Sample Category 1 
    Sample rule 1 
Sample Category 2 

我嘗試了一些查詢,我從這裏找到,但沒有工作。

這是我最後一次嘗試:

'SELECT * 
FROM ' . RULES_TABLE . ' AS parent 
    LEFT JOIN ' . RULES_TABLE . ' AS child 
    ON child.parent_id = parent.rule_id 
WHERE parent.parent_id = 0 
    AND parent.public = 1 
ORDER BY parent.cat_position, child.rule_position'; 

它返回採樣規則僅1

想法?

+0

你不能這樣做,在SQL中使用一個單一的查詢,如果這是你在問什麼?請具體而言,你可以通過對規則的類別和子查詢進行查詢,甚至可以在單個查詢中進行查詢,前提是您可以在結果中沒有規則的情況下犧牲類別,並接收每個規則的類別名稱,或者不用犧牲串聯的空類別(使用逗號或您選擇的某個字符)規則名稱 – xception

+0

我可以通過將查詢置於旁邊由另一個查詢創建的循環,但這不是建議,我不應該這樣做。這就是爲什麼我在這裏問的一個可接受的解決方案,它不包含循環查詢。 – Aborted

+0

如果您有一個不包含循環查詢的解決方案,請將其發佈。 – Aborted

回答

2

試試這個小提琴http://sqlfiddle.com/#!2/0a9c5/16,下面

SELECT c.rule_id, c.rule_title, GROUP_CONCAT(r.rule_title) 
FROM RULES_TABLE AS c 
LEFT JOIN RULES_TABLE AS r 
    ON r.parent_id = c.rule_id 
WHERE c.parent_id IS NULL AND c.public = 1 
GROUP BY c.rule_id 
ORDER BY c.cat_position, c.rule_position; 

SQL代碼冷落的代碼PHP-化的目的,以保持語法高亮,這似乎不是如果超過最大允許GROUP_CONCAT大小,反正工作

您可以增加它或使用以下版本,並在php中做更多的處理:

SELECT c.rule_id, c.rule_title, r.rule_title as r_rule_title 
FROM RULES_TABLE AS c 
LEFT JOIN RULES_TABLE AS r 
    ON r.parent_id = c.rule_id 
WHERE c.parent_id IS NULL AND c.public = 1 
ORDER BY c.cat_position, c.rule_position; 

並在php中,骨架代碼pro只有vided,與實際值填寫,假設你使用PDO和你的PDOStatement對象變種被命名爲$query

$old_rule_id = null; 
$rrt = array(); // will contain all r.rule_titles for a give c.rule_id 
while(($i = $query->fetch(PDO::FETCH_OBJ)) !== false) { 
    if($old_rule_id != $i->rule_id) { 
     if(count($rrt)) { 
      echo ... all the data for previous rule from $rrt ... 
      echo ... end of previous element ... 
      $rrt = array(); // empty it to collect new data 
     } 
     echo ... start of current element use data from $i->rule_id and $i->rule_title ... 
     $old_rule_id = $rule_id; 
    } 
    $rrt[] = $i->r_rule_title; 
} 
// the following is the same if from inside the while, minus reinitialization of $rrt; 
if(count($rrt)) { 
    echo ... all the data for previous rule from $rrt ... 
    echo ... end of previous element ... 
} 

取代之間的東西......有效的代碼

+0

'你的SQL語法有錯誤;檢查對應於你的MySQL服務器版本的手冊,在第7行使用'GROUP BY c.rule_id'附近的正確語法[1064]' – Aborted

+0

@Dugi用小提琴更新,group by必須在order by之前,無論如何它現在可以工作,唯一的問題是你在用逗號分隔的單個字符串中獲取規則名稱 – xception

+0

嗯,它確實工作。很快會接受你的答案。非常感謝:) – Aborted

-1

使用FOR XML EXPLICIT你可以得到一個層次列表。

試試這個:

SELECT 
1 Tag, 
null Parent, 
'' [root!1!name], 
null [category!2!id], 
null [category!2!name], 
null [rule!3!id], 
null [rule!3!name] 

UNION ALL 

SELECT DISTINCT 
2 Tag, 
1 Parent, 
null, 
rule_id [category!2!id], 
rule_title [category!2!name], 
null [rule!3!id], 
null [rule!3!name] 
FROM rules 
WHERE parent_id = 0 and rule_type = 'cat' 

UNION ALL 

SELECT 
3 Tag, 
2 Parent, 
null, 
parent_id [category!2!id], 
null [category!2!name], 
rule_id [rule!3!id], 
rule_title [rule!3!name] 
FROM rules 
WHERE parent_id > 0 and rule_type = 'rule' 

FOR XML EXPLICIT 

欲瞭解更多信息,請訪問http://msdn.microsoft.com/en-us/library/ms189068.aspx

+1

嗯,問題是關於mysql而不是mssql – xception