使用SQLite获取SQL树结构中所有父项的所有子项

时间:2016-11-29 22:03:59

标签: sql database sqlite

我有以下数据库模型:

CREATE TABLE IF NOT EXISTS account (
    name VARCHAR PRIMARY KEY,
    parent INTEGER REFERENCES account(name) ON UPDATE CASCADE ON DELETE CASCADE 
);

CREATE TABLE IF NOT EXISTS permission (
    name VARCHAR PRIMARY KEY
);

CREATE TABLE IF NOT EXISTS account_permission (
    account VARCHAR NOT NULL REFERENCES account(name) ON UPDATE CASCADE ON DELETE CASCADE,
    permission VARCHAR NOT NULL REFERENCES permission(name) ON UPDATE CASCADE ON DELETE CASCADE
);

DELETE FROM account;
DELETE FROM permission;
DELETE FROM account_permission;

INSERT INTO account(name) VALUES('a1');
INSERT INTO account(name) VALUES('a2');
INSERT INTO account(name, parent) VALUES('a3', 'a1');

INSERT INTO permission(name) VALUES('dummy');
INSERT INTO permission(name) VALUES('edit');
INSERT INTO permission(name) VALUES('delete');

INSERT INTO account_permission(account, permission) VALUES('a1', 'dummy');
INSERT INTO account_permission(account, permission) VALUES('a2', 'edit');
INSERT INTO account_permission(account, permission) VALUES('a3',  'delete');

我想要的是一个查询,它返回所有具有权限的帐户及其从父帐户继承的权限。在这种情况下,我希望得到这样的结果:

帐户|许可
a1 |虚拟
a2 |编辑
a3 |虚拟
a3 |删除

a1和a2并不特别,但我不知道如何编写递归查询以包含具有所有父权限和自己权限的a3。任何帮助表示赞赏。

2 个答案:

答案 0 :(得分:1)

P.S。
你应该重新设计表格 帐户应具有ID和NAME 许可应该有一个ID和一个名称 表格应通过ID连接。

迭代查询返回帐户和祖先(包括自我)的元组

+---------+----------+
| account | ancestor |
+---------+----------+
| a1      | a1       |
+---------+----------+
| a2      | a2       |
+---------+----------+
| a3      | a1       |
+---------+----------+
| a3      | a3       |
+---------+----------+

查询的其余部分用于将每个帐户的祖先与其权限进行匹配并删除冗余。

with        t 
            as
            (
                select      name     as account   
                           ,name     as ancestor

                from        account

             -- where       name = ... /* for a specific account */      

                union all

                select      t.account
                           ,a.parent    as ancestor

                from                t   
                            join    account as a
                            on      a.name = t.ancestor
                where       a.parent is not null
            )

select      distinct

            t.account
           ,ap.permission

from                    t
            join        account_permission  as ap
            on          ap.account  = t.ancestor

order by    t.account
           ,ap.permission     
;

答案 1 :(得分:0)

您还需要一个查询,它可以获取父权限并可以与union合并。这是

select * from  account_permission 
union 
select  a.name, ap.permission  from account_permission  ap,  account a where        a.parent = ap.account