数据库表中的多级用户

时间:2012-04-02 09:08:41

标签: mysql sql postgresql

我有一个表用户,其中我有一个字段'id'而另一个字段是'parent id'。我也期望在用户表中使用目标字段。

我有直到第8级层次结构的用户列表。其中A是B的父级,B是C的父级,依此类推。

例如

A   level 0
|
B   level 1
|
c   level 2

现在当我在寻找用户A.我希望使用sql查询'期望目标'来获取所有子用户。 即,当我使用A的id = id时,我可以看到A,B,C等的预期目标。

如果A,B和C的expected_targets分别为1000,500,200,则输出应为:

id      parent_id        expected_target

A_id                        1000  
B_id        A_id            500  
C_id        B_id            200 

3 个答案:

答案 0 :(得分:1)

这将完成工作 - http://sqlfiddle.com/#!2/0de1f/7

select u1.id, u1.parent_id, u1.expected_target
from users u1
left join users u2 on u1.parent_id = u2.id
left join users u3 on u2.parent_id = u3.id
left join users u4 on u3.parent_id = u4.id
left join users u5 on u4.parent_id = u5.id
left join users u6 on u5.parent_id = u6.id
left join users u7 on u6.parent_id = u7.id
left join users u8 on u7.parent_id = u8.id
where :A_id in (u1.id, u2.id, u3.id, u4.id, u5.id,
                u6.id, u7.id, u8.id, u8.parent_id)

答案 1 :(得分:1)

SET search_path='tmp';

DROP TABLE targets CASCADE;
CREATE TABLE targets
        ( id integer not null primary key
        , parent_id integer references targets(id)
        , expected_target integer
        );

INSERT INTO targets(id,parent_id,expected_target) VALUES
(1,NULL, 1000), (2,1, 500), (3,2, 200);


WITH RECURSIVE zzz AS (
        SELECT t0.id, t0.parent_id
        , 0::integer AS level
        , t0.expected_target
        FROM targets t0
        WHERE t0.parent_id IS NULL
        UNION
        SELECT t1.id, t1.parent_id
        , 1+zzz.level AS level
        , t1.expected_target
        FROM targets t1
        JOIN zzz ON zzz.id = t1.parent_id
        )
SELECT * FROM zzz
        ;

输出:

SET
DROP TABLE
NOTICE:  CREATE TABLE / PRIMARY KEY will create implicit index "targets_pkey" for table "targets"
CREATE TABLE
INSERT 0 3
 id | parent_id | level | expected_target 
----+-----------+-------+-----------------
  1 |           |     0 |            1000
  2 |         1 |     1 |             500
  3 |         2 |     2 |             200
(3 rows)

更新:如果您不希望整个树,真正的树,只有树,但只有它的子树部分,您当然可以稍微改变条件:

WITH RECURSIVE zzz AS (
        SELECT t0.id, t0.parent_id
        , 0::integer AS level
        , t0.expected_target
        FROM targets t0
        -- WHERE t0.parent_id IS NULL
        WHERE t0.id = 2
        UNION
        SELECT t1.id, t1.parent_id
        , 1+zzz.level AS level
        , t1.expected_target
        FROM targets t1
        JOIN zzz ON zzz.id = t1.parent_id
        )
SELECT * FROM zzz
        ;

答案 2 :(得分:0)

因为这是用PostgreSQL标记的:

with recursive users_tree as (
  select id, 
         parent_id, 
         expected_target, 
         1 as level
  from users
  where id = 'A_id'

  union all

  select c.id, 
         c.parent_id, 
         c.expected_target,
         p.level + 1
  from users c
    join users_tree p on c.parent_id = p.id
)
select *
from users_tree

MySQL不够先进,不足以支持这一点。在那里你需要为每个级别进行自我加入。