#php #mysql #sql #activerecord
Нужно Вывести все parent id? Пример: есть таблица id, pid 1 0 2 1 3 1 4 2 5 3 6 4 7 5 8 1 9 5 У id=9 pid=5, у 5 - 3, у 3 - 1, у 1 - 0 Для 9 ответ: 5, 3, 1, 0 Как в SQL запроссе получить родителей и подродителей для конкретного id? Благодарю за ответы
Ответы
Ответ 1
Лучшее решение для такой задачи — паттерн Таблица замыканий (Closure Table). Никаких рекурсий, никаких хранимых процедур не нужно. Уровни вложенности не ограничены. Соль в том, что для каждой записи в таблице замыканий создаются записи предок+потомок (как минимум одна: замыкание записи на саму себя). Желательно также указать расстояние от текущей записи до предка. При замыкании записи на саму себя указывается расстояние 0, между записью и родителем расстояние 1 и т.д. Чтобы получить всех предков определенной записи, нужно сделать выборку по потомку, равному идентификатору этой записи. Чтобы получить всех потомков — выборку по предку. Подробнее — по ссылке выше. Там также есть ссылка на первоисточник (презентацию Билла Карвина).Ответ 2
Как вариант - добавить в таблицу все промежуточные связи. Для этого надо добавить в таблицу дополнительный столбец level, в котором будет сохраняться уровень вложенности связи. // Удаляются все дополнительные связи $q = "DELETE FROM `table` WHERE `level`>0"; db_query($q); // Предполагая, что уровней вложенности не больше 10, // генерируются промежуточные связи с указанием уровня вложенности for ($level = 1; $level < 10; $level++) { $q = "INSERT IGNORE INTO `table` (`id`, `pid`, `level`) " ."SELECT t1.`id`, t2.`pid`, ".$level." AS `level` " ."FROM `table` t1 LEFT JOIN `table` t2 ON t2.`id`=t1.`pid` " ."WHERE t2.`pid`>=0 AND t2.`level`=".($level - 1)." " ."ON DUPLICATE KEY UPDATE `level`=VALUES(`level`)"; // Если не вставлено ни одной строки, значит все связи добавлены if (!db_query($q)) { break; } } Эту процедуру нужно будет повторять только при изменении дерева связей. Теперь можно получить все связи одним запросом, причём в том порядке, в каком они расположены в дереве SELECT * FROM `table` WHERE `id` = 9 ORDER BY `level` ASC Результат: id pid level 9 5 0 9 3 1 9 1 2 9 0 3
Комментариев нет:
Отправить комментарий