Страницы

Поиск по вопросам

понедельник, 24 февраля 2020 г.

Вывести все parent id

#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

Комментариев нет:

Отправить комментарий