Database 如何在数据库表中的行层次结构中建模和查询继承?
我有一组记录,存储为XML文件,其中XML文件以树结构排列。对于每个子记录,假定未明确说明的元素或属性从父记录继承。这很容易在数据库中建模,使用自引用外键,例如 树形结构Database 如何在数据库表中的行层次结构中建模和查询继承?,database,database-design,inheritance,Database,Database Design,Inheritance,我有一组记录,存储为XML文件,其中XML文件以树结构排列。对于每个子记录,假定未明确说明的元素或属性从父记录继承。这很容易在数据库中建模,使用自引用外键,例如 树形结构 数据库表 (在生产中,我会使用一个或多个列来存储树结构,但为了简单起见,省略了这一点。) 在这个系统中,Bar1将为属性1继承一个值0.4,Bar2将为属性2继承一个值“味道像鸡” 由于我远非任何领域的大师,我有几个关于如何最好地使用系统的问题 因为我需要能够以原始格式从数据库导出,所以我不能简单地预先计算和缓存“丢失”的
数据库表
(在生产中,我会使用一个或多个列来存储树结构,但为了简单起见,省略了这一点。) 在这个系统中,Bar1将为属性1继承一个值0.4,Bar2将为属性2继承一个值“味道像鸡” 由于我远非任何领域的大师,我有几个关于如何最好地使用系统的问题
我正在使用Django,如果这很重要的话,但我对原始SQL查询的处理还不太满意(例如,我构建了一个Django应用程序来操作,由于复杂的GROUPBY和having子句,它主要使用原始SQL)。您没有指定您的数据库,但是看看你的有向无环图链接,我发现你使用的是PostgreSQL。如果您能接受最新版本8.4,您可以尝试以下方法(这将回答您的第二个问题): 使用表格
create table Tree(
id serial primary key check(id > 0),
parent int references Tree(id),
name varchar(100) not null unique check(length(name)>0),
attr1 int,
attr2 varchar(15),
constraint charlength check(id > parent)
);
充满了这些数据
insert into Tree (name, parent, attr1, attr2)
values ('Foo', null, 5, 'high'), -- will have id 1
('Bar1', 1, null, 'low'), -- will have id 2
('Bar2', 1, null, null),
('Bar3', 2, null, null);
询问
with recursive parents(id, name, attr1, attr2, parent, level, who) as (
select id, name, attr1, attr2, parent, 1, id
from Tree t
where t.name in ('Bar3', 'Bar2')
union all
select t.id, p.name, coalesce(p.attr1, t.attr1), coalesce(p.attr2, t.attr2), t.parent, p.level+1, p.who
from parents p, Tree t
where t.id = p.parent
) select distinct on (who) who, name, attr1, attr2
from parents
order by who, level desc;
收益率(使用我的ruby程序包装查询):
关于你的第一个问题,我不知道你的意思。但也许您可以从数据库中的表示恢复XML?!?对于你的第三个问题,我希望能在这个周末发布一个储存树木的替代方案。否则我会说你的想法对我来说很好。谢谢你。公共表表达式和合并的结合非常完美。我最喜欢的存储树的方法是用unicode字符串(utf-8)对树中的位置进行编码,父级是通过删除最后一个unicode字符获得的字符串(在PostgreSQL:substring中(treepos from 1表示字符长度(treepos)-1))。如果你想了解更多,请告诉我。
insert into Tree (name, parent, attr1, attr2)
values ('Foo', null, 5, 'high'), -- will have id 1
('Bar1', 1, null, 'low'), -- will have id 2
('Bar2', 1, null, null),
('Bar3', 2, null, null);
with recursive parents(id, name, attr1, attr2, parent, level, who) as (
select id, name, attr1, attr2, parent, 1, id
from Tree t
where t.name in ('Bar3', 'Bar2')
union all
select t.id, p.name, coalesce(p.attr1, t.attr1), coalesce(p.attr2, t.attr2), t.parent, p.level+1, p.who
from parents p, Tree t
where t.id = p.parent
) select distinct on (who) who, name, attr1, attr2
from parents
order by who, level desc;
{"attr1"=>"5", "name"=>"Bar2", "attr2"=>"high", "who"=>"3"}
{"attr1"=>"5", "name"=>"Bar3", "attr2"=>"low", "who"=>"4"}