Database 数据库设计:递归多对多关系
我有Database 数据库设计:递归多对多关系,database,Database,我有n多个表,它们在多对多的基础上相互关联。我想知道如何在不为每个关系创建中间表的情况下表示这样一个模型,因为这样会产生大量的表。为此,假设n足够大,不想创建表 例如,我可能有三个表,其中n为3: Parking_Lot Car Person 一辆车可以停在很多停车场,一个停车场会有很多车。 一个人可以开很多车,一辆车可以有很多司机。 一个停车场有很多人,很多人可以在一个停车场。(这些人可能是员工,也可能只是在停车场。请不要过度分析这个示例,因为它只是一个示例。) 要对此进行建模,您将有3个表
n
多个表,它们在多对多的基础上相互关联。我想知道如何在不为每个关系创建中间表的情况下表示这样一个模型,因为这样会产生大量的表。为此,假设n
足够大,不想创建表
例如,我可能有三个表,其中n为3:
Parking_Lot
Car
Person
一辆车可以停在很多停车场,一个停车场会有很多车。
一个人可以开很多车,一辆车可以有很多司机。
一个停车场有很多人,很多人可以在一个停车场。(这些人可能是员工,也可能只是在停车场。请不要过度分析这个示例,因为它只是一个示例。)
要对此进行建模,您将有3个表(Lot、Car、Person
)和3个关系表
假设你加了第四桌食物。食物可以在许多停车场、许多汽车和许多人吃。这需要4张表+6=10张表
如何在不创建大量中间表的情况下为这种关系建模
我对这个概念更感兴趣,但我主要使用c,所以如果在.net中有一个简单的方法来实现这一点,我会洗耳恭听。您可以创建一个包含类型id/表名的关系表
relationship
relationship_type_parent
relationship_id_parent
relationship_type_child
relationship_id_child
您可以尝试创建一个中心关系表,每个实体表对应一列(允许NULL)。对于每个组合,都有一行有问题的ID 这会变得很棘手,但也可以让您建立多向关系模型——例如,A个人在停车场C驾驶B车。您可能还需要添加某种标记,例如,区分“A个人在停车场C驾驶B车”和“A个人拥有停在C场的B车” 像往常一样,“视情况而定”- 这取决于你将如何处理这些信息 在规范化表示中,映射表是区分(可能是数据丰富的)关系所必需的
在知识库表示中,一个单一类型的关系表就足够了,尽管它要求您将源ID和目标ID取消引用到不同的表中人们通常将系统与数据库(尤其是与正确的建模)联系起来,包括ACID持久性,这不是一个小功能。另一方面,.net是一个应用程序框架,与persistancee没有太多关系(它可以使用不同的后端实现持久性)。所以,如果您不确定您是否需要完整的RDBMS,或者您想讨论内存中的结构,那么您的问题,这是一个棘手的问题,实际上没有答案 否则,显式地为n加上所有二进制关系表建模被认为是一个加号 此外,您提到n+关系表,好像这是某种通用模型。但是,这既不考虑三元或高阶关系,也不考虑多个二元关系(也不考虑多个高阶关系) 我相信有人会提供模型或它的一些扩展 问题是,通过这种方法,您获得了灵活性,但失去了实际实现关系的能力 这完全取决于你为什么和为什么需要这种坚持 您可以创建某种类型的混合—例如,根据描述关系的中心表的某些特性自动创建表。如果你想要一个数据库。关系数据库 您也可以使用XML或一些对象关系映射工具等做类似的事情
你需要更好地定义这个问题。正如其他人所说,这个答案完全取决于你在做什么以及为什么要做 数据库在提取数据集以及对数据进行分类和总结方面非常出色。这就是他们设计的目的(在许多其他东西中) 它们不能很好地描述个体价值之间的复杂关系(x深n:m关系)。NoSQL运动的随机访问结构在这方面做得更好 如果您真的致力于使用经典的RDBMS,您可以使用边和节点的概念将问题建模为数据库中的图形。节点具有0:N条边和0:N个属性/值(如上所述的EAV)。边有2个节点,可能还有一个权重 您可以使用以下工具对其建模:
NODE ([node_id, entity, attribute], value)
EDGE ([src_node_id, dest_node_id], weight)
创建节点(边)之间的关系只需要向边表添加一个值
遍历结构需要一组递归查询,从当前节点查找所有可能的步骤,然后选择一个步骤到达下一个节点。对于RDBMS来说,这可能是一项密集的工作
乙二醇//
选择目标节点id
从边缘
其中src_节点_id=
按重量订购
限制1
无论你想走多远,都要用泡沫、冲洗和重复(这假设重量是一个成本而不是效益指标,并且该图是一个有向图)。我建议你需要不到10张桌子。如果一个人位于停车场B,那么食物X在同一停车场B上吃;因此,你不可能需要一张与食物和停车场相关的桌子。我会使用几乎多态的方法来解决这个问题。您可以只使用两个表,如下所示:
CREATE TABLE Node (id UNIQUEIDENTIFIER NOT NULL, PRIMARY KEY (id));
CREATE TABLE Relationships (
parent UNIQUENIDENTIFIER NOT NULL,
child UNIQUEIDENTIFIER NOT NULL,
CONSTRAINT FK_Relationship_ParentNode
FOREIGN KEY (parent) REFERENCES Node(id),
CONSTRAINT FK_Relationship_ChildNode
FOREIGN KEY (child) REFERENCES Node(id)
);
然后,所有其他实体从节点“继承”:
CREATE TABLE Person (
id UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR(50) NOT NULL,
CONSTRAINT FK_Person_Node
FOREIGN KEY (id) REFERENCES Node(id)
);
CREATE TABLE ParkingLot (
id UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR(50) NOT NULL,
address NVARCHAR(250) NOT NULL, -- bad way to model
CONSTRAINT FK_ParkingLot_Node
FOREIGN KEY (id) REFERENCES Node(id)
);
CREATE TABLE Food (
id UNIQUEIDENTIFIER NOT NULL,
name NVARCHAR(50) NOT NULL,
calories INT NOT NULL, -- hopefully only needs an int ;)
CONSTRAINT FK_Food_Node
FOREIGN KEY (id) REFERENCES Node(id)
);
现在,您可以对任意两个实体之间的关系建模,并使用联接查找它们
例如,如果你想找出哪些食物属于哪些人,你可以说:
SELECT p.name AS person, f.name AS food
FROM Person AS p
INNER JOIN Relationships AS r
ON r.parent = p.id
INNER JOIN Food AS f
ON f.id = r.child
当然,如果你想在层次结构中找到更深一点的东西,你需要具体地查询每一层。但是,因为您的实体(假设)是真实的,而不仅仅是层次结构中的级别,所以这应该是可以的:)。uhhh,我认为您只需要四个表,不管如何
SELECT p.name AS person, f.name AS food
FROM Person AS p
INNER JOIN Relationships AS r
ON r.parent = p.id
INNER JOIN Food AS f
ON f.id = r.child