Мне нужен SQL-запрос для следующей задачи COMPLEX …
Мне нужно выбрать из столбца с именем parent_id
. Если строка имеет значение 0 для parent_id
это означает, что она является категорией (она также имеет столбец type
который указывает cat
для категории), если для 1 parent_id
строки имеет значение 1 или больше, это означает, что это правило. parent_id
правила, является rule_id
категории.
Структура таблицы с некоторыми данными в ней:
Мне нужно выбрать в какой-то мере, что КАЖДАЯ категория, имеет своих детей под ней. Из рисунка мы получим следующее:
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