如何从递归CTE中排除条目?

时间:2014-04-28 20:45:25

标签: sql sqlite

如何使用Sqlite从递归CTW中排除条目?

CREATE TABLE GroupMembers (
    group_id        VARCHAR,
    member_id       VARCHAR
);

INSERT INTO GroupMembers(group_id, member_id) VALUES
    ('1', '10'),
    ('1', '20'),
    ('1', '30'),
    ('1', '-50'),
    ('2', '30'),
    ('2', '40'),
    ('3', '1'),
    ('3', '50'),
    ('4', '-10'),
    ('10', '50'),
    ('10', '60');

我想要一个查询,它会给我组中的成员列表(递归)。但是,第一个字符为“ - ”的成员表示减号后面的ID不在组中。

例如,'1'的成员是'10','20','30'和'-50'。然而,'10'是一个群体,所以我们需要添加它的孩子'50'和'60'。但是,' - 50'已经是会员,因此我们不能包含'50'。总之,'1'的成员是'10','20','30',' - 50'和'60'。

似乎此查询应该有效:

WITH RECURSIVE members(id) AS (
    VALUES('1')
    UNION
    SELECT gm.member_id 
        FROM members m
        INNER JOIN GroupMembers gm ON mg.group_id=m.id
        LEFT OUTER JOIN members e ON '-' || gm.member_id=e.id
        WHERE e.id IS NULL
)
SELECT id FROM members;

但我收到错误:multiple references to recursive table: members

如何修复/重写它以做我想做的事?

注意:在结果集中是否返回'-50'条目无关紧要。

1 个答案:

答案 0 :(得分:2)

我没有可用于测试的SQLite,但假设-50也意味着也应该排除50,我认为您正在寻找:

WITH RECURSIVE members(id) AS (
    VALUES('1')
    UNION
    SELECT gm.member_id 
    FROM GroupMembers gm 
      JOIN members m ON gm.group_id=m.id
    WHERE member_id not like '-%'
      AND not exists (select 1 
                      from groupMembers g2
                      where g2.member_id = '-'||gm.member_id)
)
SELECT id 
FROM members;

(上述作品在Postgres中)

您通常从递归部分的基表中选择,然后再连接回实际的CTE。然后使用常规where子句对不需要的行进行过滤,而不是再次加入CTE。递归CTE定义为在JOIN找不到更多行时终止。

SQLFiddle(Postgres):http://sqlfiddle.com/#!15/04405/1

在需求发生变化后(已详细说明)

编辑

因为您需要根据位置排除行(您在原始问题中未提供的详细信息)。过滤器只能在CTE的完成。我再次无法用SQLite测试,只能使用Postgres:

WITH RECURSIVE members(id, level) AS (
    VALUES('4', 1)
    UNION
    SELECT gm.member_id, m.level + 1
    FROM GroupMembers gm 
      JOIN members m ON gm.group_id=m.id
)
SELECT m.id, m.level
FROM members m
where id not like '-%'
  and not exists (select 1 
                  from members m2
                  where m2.level < m.level 
                    and m2.id = '-'||m.id);

更新了SQLFiddle:http://sqlfiddle.com/#!15/ec0f9/3