如何在SQL中建模关系“A包含在B或A = B”?

时间:2012-06-28 13:19:05

标签: sql ms-access database-design

问题似乎很简单,但我似乎找不到在MS Access中实现它的方法。我有一组国家,以及这些国家内的一组区域。为了模拟国家或地区之间的天然气交换,我正在定义“平衡区”。这个平衡区可以是整个国家,也可以是法国北部的一个地区。

到目前为止,我有三个表:country-> region->平衡区。在该模型中,一些区域是“真实”区域,即实际国家子集,一些区域与国家相同。我使用单个字符标记来识别与国家/地区代码组合的区域,并使用特殊字符“x”来表示此特定区域与国家/地区相同的事实。然而,通过这种方法,我无法表达“x”特殊的事实,并且在使用时,它指定整个国家。

使用NULL代替我似乎很自然。但是,在这种情况下,我不能在(country,tag)上有一个唯一的索引,因为Access将允许多个(country,NULL)记录。

有人对此有所了解吗?

3 个答案:

答案 0 :(得分:2)

看来你需要这样的东西:

enter image description here

CHECK (
    (COUNTRY_ID IS NULL AND REGION_ID IS NOT NULL)
    OR (COUNTRY_ID IS NOT NULL AND REGION_ID IS NULL)
)

在BALANCING_ZONE表中,COUNTRY_ID和REGION_ID都是NULL,但CHECK强制确保其中任何一个在任何给定时间都是非NULL。

因此,要将平衡区域连接到国家/地区,只需设置BALANCING_ZONE.COUNTRY_ID,并将BALANCING_ZONE.REGION_ID保留为NULL。要将其连接到某个区域,请执行相反的操作。


不幸的是,Access仅支持部分外键的MATCH FULL行为。如果它支持MATCH SIMPLE(与大多数DBMS一样),您也可以执行以下操作:

enter image description here

在BALANCING_ZONE表中,COUNTRY_ID不能为NULL且REGION_NO为NULL。

要将平衡区域连接到国家/地区,只需设置BALANCING_ZONE.COUNTRY_ID并将BALANCING_ZONE.REGION_NO保留为NULL。要连接到某个区域,请同时设置它们。

答案 1 :(得分:1)

听起来你只需要1张国家和地区的表,称之为“LandMass”,“Area”或其他。

LandMass
========
LandMassId
LandMassParentId
LandMassName
LandMassType

在这种情况下,你可以一直到一个土地所有者:

Type="LandOwner"
Parent="MyCity"

Type="City"
Parent="MyState"

Type="State"
Parent="Region"

Type="Region"
Parent="Country"

Type="Country"
Parent="Continent"

Type将是LandMassType表的外键

Parent将是返回LandMass表的外键

您还可以创建计算列,这些列可以总结城市级别的土地所有者类型,将城市类型总结为州级别,等等。

视图也没有超出范围......可以在每个级别创建可更新视图,这些视图基本上按类型对数据进行分区。


另一方面,也许你需要这种类型的设计:

Parcel table
============
Id
ParentId
Name
Type
etc..

Region table
============
Id
Name
etc..

Parcel_Region table
===================
ParcelId
RegionId

这可以让您更灵活地定义一个可以由任意数量的地块组成的“区域”,尽管有边界。但是,您必须使用宗地表将这些结果联合起来,其中宗地不参与某个区域。换句话说,所有地块都将被视为地区,特定地区可能包含任意数量的地块。


这就是所有魔法的地方(我认为也可以应用于你的模型)

Type列也可以像bitmask一样对待:

Type 0 = none;
Type 1 = land owner
Type 2 = city
Type 4 = state
Type 8 = country
Type 16 = continent

所以如果你想,区域X可以是一个城市和一个州,给它一个类型值(城市|州)= 6基础数学很简单:

if((Type & 4) > 0) then it's a state.  
if((Type & 2) > 0) then it's a city

答案 2 :(得分:0)

使用您所拥有的 - 将您的x字段数据类型更改为布尔值或访问等效项 - 0/1,True / False,是/否。创建一个新列并根据X更新数据,重命名新列,删除旧列,并将新列重命名为您选择的名称。接下来,当你插入到Region(或者这个X存在的地方 - 我不清楚在balancezone中是什么),如果它是或不是一个子集(无论你命名它,父类等),更新它是真还是假。

country
---------
countryid
name, decript, whatever other fields


region
--------
regionid
countryid FK
subset (0 or 1, T/F, Y/N)
name, decript, whatever other fields