我有n
个以多对多方式相关的表格。我想知道如何在不为每个关系创建中间表的情况下表示这样的模型,因为这会导致一些大量的表。为此,假设n
足够大,不想创建表。
例如,我可能有三个表,其中n是3:
Parking_Lot
Car
Person
一辆汽车可停放在许多停车场,停车场将停放许多汽车。 一个人可以开很多车,一辆车可以有很多车手。 停车场有很多人,许多人可以在停车场。 (人们可能是雇员,或者他们可能只是在停车场。请不要过分分析这个例子,因为这只是一个例子。)
要对此进行建模,您将拥有3个表(Lot, Car, Person
)和三个关系表。
假设您添加了第4张食物。许多停车场,许多汽车和许多人都可以食用食物。这需要4个表+ 6 = 10个表。
如何在不创建大量中间表的情况下建模这种关系?
我对这个概念更感兴趣,但我主要使用c#所以如果有一个整洁的可能在.net中实现这一点我很满意。
答案 0 :(得分:3)
我通过使用几乎多态的方法来解决这个问题。您可以使用两个表,如下所示:
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)
);
然后所有其他实体从Node继承“
”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
当然,如果您想在层次结构中找到更深层次的内容,则需要专门查询每个级别。但是因为你的实体(假设)是真实的东西,而不仅仅是层次结构中的层次,那应该没问题。)。
答案 1 :(得分:1)
这取决于您将如何处理信息
在规范化表示中,映射表是区分(可能是数据丰富的)关系的必要条件
在知识库表示中,单个类型的关系表就足够了,但它要求您将源和目标ID取消引用到不同的表
答案 2 :(得分:0)
你可以在其中创建一个带有类型id /表名的关系表。
relationship
relationship_type_parent
relationship_id_parent
relationship_type_child
relationship_id_child
答案 3 :(得分:0)
您可以尝试使用中央关系表,每个实体表都有一列(允许NULL)。对于每个组合,都有一行包含有问题的ID。
这很棘手,但也可以让你对多路关系进行建模 - 例如人在停车场C驾驶汽车B.你可能想要添加某种标签,例如区分“停车场C中驾驶汽车B的人”和“停在C地停放汽车B的人A”。
答案 4 :(得分:0)
人们通常将系统与数据库(尤其是正确的建模)相关联,包括ACID持久性,这不是一个小功能。另一方面.net是应用程序的框架,与persistancee没有多大关系(它可以使用不同的后端来持久化)。因此,如果您不确定是否需要完整的RDBMS,或者您想要在内存结构中讨论,那么您的问题(一开始就很棘手)实际上没有答案。
否则,显式建模n加上所有二元关系表被认为是一个加号。
另外,你提到n +关系表,好像那是某种通用模型。但是,这不会处理三元或更高阶的关系,也不会处理多个二元关系(也不是多个高阶关系)。
我相信有人会提供EAV模型或某些扩展程序。
问题在于,通过这种方法,您可以获得灵活性,但却无法实际实现关系。
这一切都取决于为什么以及你需要这种持久性。
您可以创建某种混合 - 例如,根据描述您的关系的中心表自动创建表。如果你想要一个数据库。关系数据库。
您也可以使用XML或某些对象关系映射收费等进行类似的操作......
您需要更好地定义问题。
答案 5 :(得分:0)
正如其他人所说,这个答案完全取决于你正在做什么以及你为什么这样做。
数据库非常适合撤回数据的SETS以及对数据进行分类和汇总。这就是他们设计的(在许多其他事情中)。
它们在描述各个值之间的复杂关系(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)
在节点(边缘)之间创建关系只需要向EDGE表添加一个值。
遍历结构需要一组递归查询,查找当前节点的所有可能步骤,然后选择一个进入下一个节点。这对于RDBMS来说可能非常密集。
EG //
SELECT dest_node_id
FROM EDGE
WHERE src_node_id = <<This Node ID>>
ORDER BY weight ASC
LIMIT 1
在你想去的路径上泡沫,冲洗并重复(这假设权重是成本而不是效益指标,图表是有向图)。
答案 6 :(得分:0)
我建议你需要少于10张桌子。考虑一个人吃食物X.如果人A位于停车场B,则食物X在同一停车场B吃;因此,您可能不需要有关食品和停车场的表格。
答案 7 :(得分:0)
呃,我想如果您使用具有一对多关系的“ category”表,则无论n有多高,您都只需要四个表。
表1 =您将人员,汽车,停车场,食物全部放入一张桌子的“事物”,并根据需要添加任意列
表2 =“事物关系”,在这里您可以将一个人与汽车,一个人与停车场,一个食物与汽车等相匹配....
表3 =“类别”,即人,停车场,汽车,食物
表4 =“类别关系”,您可以为每件事定义一个类别
也许我错了idk,但是如果您不希望表的数量成倍增加,这似乎是最好的解决方案