树格式或添加级别的MYSQL输出(父子)
下面是我桌上的东西 我的桌子 什么,我想要的是如下使用MYSQL树格式或添加级别的MYSQL输出(父子),mysql,sql,tree,format,parent-child,Mysql,Sql,Tree,Format,Parent Child,下面是我桌上的东西 我的桌子 什么,我想要的是如下使用MYSQL C1 G1 G2 G3 D1 D2 G4 D3 D4 C2 G5 G6 G7 G8 请让我知道这在MYSQL中是否可行。输出类似于树 更新1 如果我得到下面这样的新表,也可以使用。 ++++++++++++++++++++++++++++++++++++++++ Parent + Child + PLevel + CLevel ++++++++++++
C1
G1
G2
G3
D1
D2
G4
D3
D4
C2
G5
G6
G7
G8
请让我知道这在MYSQL中是否可行。输出类似于树
更新1
如果我得到下面这样的新表,也可以使用。
++++++++++++++++++++++++++++++++++++++++
Parent + Child + PLevel + CLevel
++++++++++++++++++++++++++++++++++++++++
C1 + G1 + 1 + 2
C1 + G2 + 1 + 2
C1 + G3 + 1 + 2
G3 + D1 + 2 + 3
G3 + D2 + 2 + 3
C1 + G4 + 1 + 2
G4 + D3 + 2 + 3
G4 + D4 + 2 + 3
C2 + G5 + 1 + 2
C2 + G6 + 1 + 2
C2 + G7 + 1 + 2
C2 + G8 + 1 + 2
++++++++++++++++++++++++++++++++++++++++
注意:我的级别从1开始(在示例中,我的级别从0开始)。如果我得到这个级别从0开始的新表,也可以。MySQL和RDBMS通常不适合这种结构。您可能必须使用客户端递归来实现这一点
如果递归仅限于三个深度,如您的示例所示,则可以使用联接进行递归,但对于较深的树来说,它的可伸缩性不是很强。虽然不能使用单个查询,但可以使用存储过程。。。唯一的先决条件是,您需要在现有的示例表中再添加2条记录,以表示“C1”和“C2”是顶层。。。添加一条记录,其中“父级”字段为空,子级为“C1”,另一个为“C2”。这将“准备”最顶层的父级。对于后续层次关联,否则您没有顶级层次的起始“基础”。它还需要一个“主键”列(我在这个脚本中创建了一个“IDMyTable”,它只是1-x顺序的,但是假设您的表上有一个自动递增列来代替它) 我已经包含了所有的输出列来显示它是如何构建的,但是这个例程的前提是基于预期的列输出创建一个表,但是在构建过程中额外保留了下游的层次表示。为了确保它们在层变深时保持正确的方向,我将在“ID”列中添加内容——您将看到它在最终结果集中是如何工作的 然后,在最终的结果集中,我根据层次结构数据的深度预先填充空间 循环将根据在前面的结果集中找到的父记录添加任何记录,但前提是尚未添加ID(防止重复) 要查看循环顺序是如何不断追加的,您可以运行最后一个查询,而不使用ORDERBY,并查看每个迭代是如何限定和添加上一个层次结构级别的
-- --------------------------------------------------------------------------------
-- Routine DDL
-- Note: comments before and after the routine body will not be stored by the server
-- --------------------------------------------------------------------------------
DELIMITER $$
CREATE DEFINER=`root`@`localhost` PROCEDURE `GetHierarchy2`()
BEGIN
-- prepare a hierarchy level variable
set @hierlvl := 00000;
-- prepare a variable for total rows so we know when no more rows found
set @lastRowCount := 0;
-- pre-drop temp table
drop table if exists MyHierarchy;
-- now, create it as the first level you want...
-- ie: a specific top level of all "no parent" entries
-- or parameterize the function and ask for a specific "ID".
-- add extra column as flag for next set of ID's to load into this.
create table MyHierarchy as
select
t1.IDMyTable,
t1.Child AS Parent,
@hierlvl as IDHierLevel,
cast( t1.IDMyTable as char(100)) FullHierarchy
from
MyTable t1
where
t1.Parent is null
OR t1.Parent = '';
-- how many rows are we starting with at this tier level
set @lastRowCount := ROW_COUNT();
-- we need to have a "primary key", otherwise our UPDATE
-- statement will nag about an unsafe update command
alter table MyHierarchy add primary key (IDMyTable);
-- NOW, keep cycling through until we get no more records
while @lastRowCount > 0 do
-- NOW, load in all entries found from full-set NOT already processed
insert into MyHierarchy
select
t1.IDMyTable,
t1.Child as Parent,
h1.IDHierLevel +1 as IDHierLevel,
concat_ws( ',', h1.FullHierarchy, t1.IDMyTable ) as FullHierarchy
from
MyTable t1
join MyHierarchy h1
on t1.Parent = h1.Parent
left join
MyHierarchy h2
on t1.IDMyTable = h2.IDMyTable
where
h2.IDMyTable is null;
set @lastRowCount := row_count();
-- now, update the hierarchy level
set @hierLevel := @hierLevel +1;
end while;
-- return the final set now
select
*, concat( lpad( ' ', 1 + (IDHierLevel * 3 ), ' ' ), Parent ) as ShowHierarchy
from MyHierarchy
order by FullHierarchy;
END
首先为计算级别创建递归函数
function fn_CalcLevel(int @ID)
As Begin
Declare @ParentID int
Select @ParentID = ParentID From Table1 where ID = @ID
IF (@ParentID IS NULL) Return 1 Else Return 1+fn_CalcLevel(@ParentID)
End
然后创建如下所示的查询
Select *, fn_CalcLevel(Table1.ID) as Level
From Table1
如果您稍微调整一下您的表,您可以使用以下内容:
SELECT Child,CONCAT(LPAD('',Clevel,' '),Child),etc from tablename
重新构造是,您需要将中的根节点作为父节点为0的行。您可以添加自己的父/子/C级别的订单,以获得所需的序列
我知道这是几年前的事了,但这可能会为其他人节省一些精力 这可能会对您有所帮助,正如其他人已经说过的,MySQL不支持递归函数,因此它不适合这种存储分层数据的邻接列表模型。您可能需要考虑重构数据以使用嵌套集合或闭包表。有关更多信息,请参阅。不一定是递归;只要语言有引用,就可以使用哈希表而无需递归。对对象的所有ID进行散列,让子数组引用其中的任何内容,您可以在一个
while
循环中完成所有操作。这有点离题,但您不只是将递归向下移动到语言中吗?在某些时候,确实需要找到每个节点的每个子节点?@Cylindric:显然,是的:)您需要递归来遍历树,例如在打印树时。我只是说你不需要它来构建它。现代的数据库管理系统一般都很擅长使用递归查询。MySQL只是落后了很多年
SELECT Child,CONCAT(LPAD('',Clevel,' '),Child),etc from tablename