如何使用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'条目无关紧要。
答案 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