如何获得postgres中的兄弟姐妹列表?

时间:2018-04-10 10:45:11

标签: sql postgresql hierarchical-data family-tree

以下是我的架构: -

postgres=# \d check_user;
                         Table "public.check_user"
 Column |  Type   |                        Modifiers
--------+---------+---------------------------------------------------------
 id     | integer | not null default nextval('check_user_id_seq'::regclass)
 name   | text    |
 gender | text    |
Indexes:
    "check_user_pkey" PRIMARY KEY, btree (id)
Referenced by:
    TABLE "parent" CONSTRAINT "parent_left_node_fkey" FOREIGN KEY (left_node) REFERENCES check_user(id)
    TABLE "parent" CONSTRAINT "parent_right_node_fkey" FOREIGN KEY (right_node) REFERENCES check_user(id)
    TABLE "spouse" CONSTRAINT "spouse_husband_fkey" FOREIGN KEY (husband) REFERENCES check_user(id)
    TABLE "spouse" CONSTRAINT "spouse_wife_fkey" FOREIGN KEY (wife) REFERENCES check_user(id)


postgres=# \d parent;
                           Table "public.parent"
   Column   |  Type   |                      Modifiers
------------+---------+-----------------------------------------------------
 id         | integer | not null default nextval('parent_id_seq'::regclass)
 left_node  | integer |
 right_node | integer |
Indexes:
    "parent_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "parent_left_node_fkey" FOREIGN KEY (left_node) REFERENCES check_user(id)
    "parent_right_node_fkey" FOREIGN KEY (right_node) REFERENCES check_user(id)

postgres=# \d spouse
                          Table "public.spouse"
 Column  |  Type   |                      Modifiers
---------+---------+-----------------------------------------------------
 id      | integer | not null default nextval('spouse_id_seq'::regclass)
 husband | integer |
 wife    | integer |
Indexes:
    "spouse_pkey" PRIMARY KEY, btree (id)
Foreign-key constraints:
    "spouse_husband_fkey" FOREIGN KEY (husband) REFERENCES check_user(id)
    "spouse_wife_fkey" FOREIGN KEY (wife) REFERENCES check_user(id)

以下是每个表中的数据: -

postgres=# select * from check_user;
 id | name | gender
----+------+--------
  4 | a    | m
  1 | x    | m
  2 | y    | f
  3 | z    | f
  7 | c3   | f
  6 | c2   | m
  5 | c1   | m
  8 | b    | m
  9 | c4   | f
(9 rows)

postgres=# select * from spouse;
 id | husband | wife
----+---------+------
  1 |       1 |    2
  2 |       1 |    3
  3 |       4 |    2
  4 |       8 |    3
(4 rows)

postgres=# select * from parent;
 id | left_node | right_node
----+-----------+------------
  1 |         1 |          5
  2 |         2 |          5
  3 |         1 |          6
  4 |         3 |          6
  5 |         4 |          7
  6 |         2 |          7
  7 |         8 |          9
  8 |         3 |          9

现在,我想找到用户c1的步骤兄弟。通过兄弟姐妹,我的意思是,用户是c1父亲之母的儿子,但不是两者。

我正在使用以下查询: -

 with user_parents as (
    select  child.id as child_id, child.name as child_name, parent_dtls.id as parent_id,
parent_dtls.name as parent_name, child.gender as child_gender, parent_dtls.gender as parent_gender
from check_user child
        inner join parent on child.id=parent.right_node
        inner join check_user parent_dtls on parent.left_node=parent_dtls.id
    ),
fathers as (select * from user_parents where user_parents.parent_gender='m'),
mothers as (select * from user_parents where user_parents.parent_gender='f'),
my_father as (select * from fathers where fathers.child_id=5),
my_mother as (select * from mothers where mothers.child_id=5)
select   user_.id as "user_id", fathers.parent_id as "father_id", my_father.parent_id "my_father_id",
mothers.parent_id as "mother_id", my_mother.parent_id as "my_mother_id" from parent parent_dtls
left join my_father on parent_dtls.left_node=my_father.parent_id
left join my_mother on parent_dtls.left_node=my_mother.parent_id
inner join check_user user_ on user_.id=parent_dtls.right_node
left join fathers on parent_dtls.right_node=fathers.child_id
left join mothers on parent_dtls.right_node=mothers.child_id where my_father.parent_id is null and my_mother.parent_id is null;

但是我和其他兄弟姐妹一起获得了其他行。

我在做什么?此外,如果在上述查询中存在效率,请评论效率低下。

提前致谢。

1 个答案:

答案 0 :(得分:0)

我更喜欢逐步解决任务。所以代码是这样的:

//select the child id with child_id as ( select id from check_user where name = 'c1'), //select parents ids parents as ( select left_node, right_node from parent where id in (select * from child_id) ) select * from check_user where id in ( select id from parent where //child of one parents, not both (left_node in (select left_node from parents) and right_node not in (select right_node from parents)) or (left_node not in (select left_node from parents) and right_node in (select right_node from parents) ) )

P.S。 看起来,根据任务描述,配偶表是不必要的。

相关问题