1.设计表
表名:genealogy(族谱)
字段:1.id(编号),2.name(姓名),3.parent_id(父亲编号,没有父亲值为-1)
sql:
CREATE TABLE `genealogy` (
`id` int NOT NULL AUTO_INCREMENT ,
`name` varchar(255) NOT NULL ,
`parent_id` int NOT NULL DEFAULT -1 ,
PRIMARY KEY (`id`)
)
2.录入模拟数据
模拟数据:
idnameparent_id
1张宗主-12张大13张小14张大傻25张小傻36张大傻傻4
sql:
INSERT INTO genealogy (id, NAME, parent_id)
VALUES
(1, '张宗主' ,- 1),
(2, '张大', 1),
(3, '张小', 1),
(4, '张大傻', 2),
(5, '张小傻', 3),
(6, '张大傻傻', 4)
3.编写sql
最终sql,以张大傻傻为例:
SELECT
genealogy.*
FROM
genealogy,
(
SELECT
@id AS id,
(
SELECT
@id := parent_id
FROM
genealogy
WHERE
id =@id
) AS parent_id
FROM
genealogy,
(SELECT @id := 6) tab
WHERE
@id !=- 1
) temp
WHERE
temp.id = genealogy.id;
4.分析sql
1.需要一个可变的查询条件
id
id 6 查出父亲 parent_id
4 这是第一次查询,需要做递归查询,第二次查询
id值为
4
sql中定义变量,并能在select中语句使用
其中@
id:=?为赋值。
2.如何使用临时表
tab,跟族谱表做关联查询,join两张表,且是full join:
SELECT
@
id AS
id,
(
SELECT
@
id := parent_id
FROM
genealogy
WHERE
id =@
id
) AS parent_id
FROM
genealogy,
(SELECT @
id :=
6)
tab
@
id的值就是当次查询的编号
id,所以@
id AS
id,而@
id值需要更改,在做完当次查询后,再做一次字段查询,
嗯,这里是最纠结的地方,原谅我不想查资料。
(无从查起,不知道咋提问,去官网翻文档?哦的天,茫茫资料海,想想生畏,还是算了)
给个大胆的猜测,@
id的工作原理是逐行执行,并在执行时,保留瞬时值,而不是在得到整个表结果的时候,
一次性替换它的最终值,最终值没有意义肯定是-
1。
那么在这个大前提下,流程就简单了,full join操作提供了循环次数,为genealogy的记录数,
每行数据的生成应该是这样的,读下当前@
id值,写入
id值,再执行字段查询得出parent_id值,
并覆盖掉原来的@
id值,单次循环结束,以此类推。
所以在没有加
where id!=-
1前,查出的记录数肯定同genealogy的记录数相等,并且无效的记录的
id值必然为-
1。
其实到了这步接下来的操作就无需解释了,嗯,那下面略。