mysql 子父类查询,在select中使用@的示例

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.录入模拟数据

模拟数据:

id name parent_id
1 张宗主 -1
2 张大 1
3 张小 1
4 张大傻 2
5 张小傻 3
6 张大傻傻 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中语句使用---特殊临时表 (SELECT @id := 6) tab
其中@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。  
其实到了这步接下来的操作就无需解释了,嗯,那下面略。

猜你喜欢

转载自blog.csdn.net/u013062667/article/details/79868001
今日推荐