SELECT и список дочерних и родительских

Мне нужен SQL-запрос для следующей задачи COMPLEX …

Мне нужно выбрать из столбца с именем parent_id . Если строка имеет значение 0 для parent_id это означает, что она является категорией (она также имеет столбец type который указывает cat для категории), если для 1 parent_id строки имеет значение 1 или больше, это означает, что это правило. parent_id правила, является rule_id категории.

Структура таблицы с некоторыми данными в ней: Данные таблицы phpMyAdmin

Мне нужно выбрать в какой-то мере, что КАЖДАЯ категория, имеет своих детей под ней. Из рисунка мы получим следующее:

 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 .

Идеи?

Попробуйте эту скрипку http://sqlfiddle.com/#!2/0a9c5/16 , код sql ниже

 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; 

упустил php-ization кода для поддержки подсветки синтаксиса, который, похоже, не работает

Если вы превысите максимально допустимый размер 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, только скелетный код, заполняется фактическими значениями, если вы используете pdo, а ваш pdostatement var называется $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 ... } 

заменить материал между … с действительным кодом

Используя 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