сложные строки дерева SQL
-
12-09-2019 - |
Вопрос
структура таблицы
id | message | reply_id
1 | help me! | 0
434 | love to | 1
852 | didn't work | 434
0110 | try this | 852
2200 | this wont | 0
5465 | done. :) | 0110
у меня есть идентификатор «852», который находится в середине древовидного меню, но я хочу получить все предыдущие и следующие связанные строки, поэтому я хочу получить следующие результаты:
Помоги мне!> с удовольствием > не получилось > попробовать > готово.:) (этот результат выглядит так после цикла php, но цикл начинается с идентификатора стартера 1 с идентификатором ответа 0.
ПРИМЕЧАНИЕ:Идентификатор 2200 не появился в результате, поскольку он не входит в группу.
Решение
Существует несколько вариантов упрощения работы с иерархической информацией в SQL:
Общие табличные выражения (согласно стандарту SQL-2003) поддерживают рекурсивные запросы SQL к используемым вами типам данных родительского идентификатора.Пока что MySQL не поддерживает эту функцию.PostgreSQL 8.4, Microsoft SQL Server и IBM DB2 являются примерами брендов СУБД, поддерживающих синтаксис CTE.Oracle также имеет собственное расширение синтаксиса SQL, поддерживающее рекурсивные запросы.
Вложенные наборы (левое/правое решение, о котором упоминает @phantombrain) — это решение, подробно описанное в книге Джо Селко «Деревья и иерархии в SQL для Smarties», а также в многочисленных статьях и сообщениях в блогах в Интернете.
Перечисление путей (также известный как «Материализованный путь») сохраняет строку в каждой строке иерархии, чтобы отметить путь предков этой строки.Объедините это с
LIKE
запросы для сравнения строки пути с путями ее предков и потомков.Таблица закрытия (также известное как отношение транзитивного замыкания) использует вторую таблицу для хранения всех отношений «предок-потомок», а не только непосредственного родителя, как в используемом вами проекте.Многие типы запросов становятся проще, когда все пути сохранены.
Гибридные решения также существуют.Например, сохраните непосредственный родительский идентификатор, как вы это делаете, а также корень дерева.Теперь вы можете получить все остальные строки в той же иерархии, извлечь их в код приложения и отсортировать дерево с помощью обычных структур данных.
Другие советы
Предполагая, что это пункты меню, а не что-то очень динамичное, например форум, я бы рекомендовал изменить схему, добавив значения левого и правого угла для каждого элемента.Все идентификаторы между левым и правым значениями являются дочерними элементами запрашиваемого узла.Таким образом, можно легко выполнить один запрос для получения значений левого и правого полей, а второй запрос — для получения подэлементов.
Видеть http://www.sitepoint.com/print/hierarchical-data-database/ Чтобы получить больше информации
Рекурсия — самый элегантный способ сделать это, но я не думаю, что mySql поддерживает ее в пользовательских функциях или хранимых процедурах.Я бы предложил выполнить цикл во временной таблице или табличной переменной, чтобы получить ваши идентификаторы, затем присоединиться к таблице и запросить результаты обратно.Я не очень хорошо знаю mySql, так что это не проверено, но что-то в этом роде.
CREATE TEMPORARY TABLE tbl (myid int, ViewOrder int);
Set @ifoundID=IdYourLookingFor;
Set @iStartID=@ifoundID;
Set @iOrder=0;
INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);
BEGIN --get the ones going up
WHILE (@ifoundID Is Not Null) DO
SELECT @ifoundID=reply_id FROM YourTable WHERE id=@ifoundID; --find the next id
SET @iOrder1=@iOrder-1; --increment the order
INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid
END WHILE;
END
Set @ifoundID=@iStartID;
BEGIN --get the ones going down
WHILE (@ifoundID Is Not Null) DO
SELECT @ifoundID=id FROM YourTable WHERE reply_id=@ifoundID; --find the next id
SET @iOrder1=@iOrder+1; --increment the order
INSERT INTO tbl(myid,ViewOrder)VALUES(@ifoundID,@iOrder);--save the nextid
END WHILE;
END
SELECT * FROM tbl INNER JOIN YourTable ON tbl.myid=YourTable.id ORDER BY ViewOrder
надеюсь, это поможет