如何使用表中不同数量的列设计数据库

时间:2012-02-24 16:16:53

标签: mysql database postgresql database-design

我们假设您正在创建一个存储不同国家/地区特征的系统。将有相同的基本栏目,如姓名,人口,首都等。但是,让我们说除了它之外,你想要存储一些国家特定的信息,如最高的山,最近的海洋,最着名的食物等。这些列将是不同的国家。

如何使用像MySQL这样的关系数据库来完成。 我知道使用像MongoDB这样的无模式NoSQL数据库可以更容易地将每个国家/地区存储为单独的文档。但是可以使用关系数据库完成这样的事情吗?

8 个答案:

答案 0 :(得分:4)

只有文本字段,您需要另外两个表:

  • 属性(包含属性的名称,例如“最高峰”)
  • country_properties(包含国家/地产对的值:例如:国家/地区的ID“奥地利”,属性“最高山”的ID,“山的名称”)

或者,如果只有几个属性,只需为未知值存储NULL。

答案 1 :(得分:3)

它可以。正如我今天通过询问another question on SO所学到的,这被称为EAV(用于实体 - 属性 - 值模型)。我在wikipedia上找到了一个有趣的解释。

答案 2 :(得分:0)

你真的不应该用标准的关系数据库来做这件事。而是将额外数据存储在单独的表中,并使用引用该国家/地区表的外键。

只有有时使用的列通常违反了关系完整性。有时候出于性能原因这是必要的,但如果你不关心这一点,我强烈建议你选择最合适的关系模型。

答案 3 :(得分:0)

如果每个国家/地区的列确实不同,请创建一个名为country_field的新表,其中包含以下列

  • country_id(FK到您的国家/地区表)
  • field_name varchar
  • field_value varchar

将您所在国家/地区的特定属性存储在此表中,每个国家/地区特定字段都有一行。

答案 4 :(得分:0)

我有一个类似的应用程序需要mySQL的情况,我发现最灵活的选项对我们来说是将数据分成多个表,例如我们可能有一个名为country_register的表

country_id (int primary key) | country_name 

然后我们有另一个名为country_data的表

tbl_id (int primary key) | country_id (int foreign key) | country_property (varchar index) | country_data (text indexed as fulltext)

基本上country_property是您获取数据的参考,因此它可以是例如“population”,然后country_data将拥有您想要的实际数据。

然后您将使用JOIN,每行将包含您需要的所有数据。这是我所知道的使用mySQL的最灵活的结构,它适用于这些类型的任务。

我希望这会有所帮助。

答案 5 :(得分:0)

我们以山为例:

CREATE TABLE `countries` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `name` VARCHAR(255),
  PRIMARY KEY (`id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

CREATE TABLE `mountains` (
  `id` INT(11) UNSIGNED NOT NULL AUTO_INCREMENT,
  `country_id` INT(11) UNSIGNED NOT NULL,
  `name` VARCHAR(255),
  `height` INT(10) NOT NULL,
  PRIMARY KEY (`id`),
  KEY `fk_country_id` (`country_id`)
) ENGINE=InnoDB  DEFAULT CHARSET=utf8;

您可以通过以下方式创建SELECT - 查询,以获得每个国家/地区的最高峰:

SELECT c.name, m.name, MAX(m.height) as height
FROM mountains m
JOIN countries c
ON c.id = m.country_id
GROUP BY m.country_id;

答案 6 :(得分:0)

您所描述的是数据结构的超类型 * 子类型 *。 超级类型是所有数据中的常见数据(在您的国家/地区)。 子类型是每组数据(在您的国家/地区)中唯一的。您将拥有一个超类型表格**和几个子类型表格。子类型表包含链接回超类型表的FKeys。

这使您可以通过超类型查询所有内容,然后按子类型进行深入分析。

* 强文 *各国想到的子类型是:
Mountanous
内陆
OceanView

你甚至可以通过大陆将它们分开: 北美洲
南美洲
亚洲
大洋洲

答案 7 :(得分:0)

我们有三种策略:

  1. 全元设计,国家可空属性的值将被放入价值收集表。例如:

    country(country_id,非null-attr-1,非null-attr-2,非null-attr -....) meta_attr(attr_id,attr_desc)(如果需要I18N,可能会更复杂) attr_value(country_id,attr_id,attr_value)

  2. 部分元设计,使用表的子类来引用国家的主表。如果您可以将某个数据实例分类为非null属性的集合,则此方法可用。例如:

    country(country_id,非null-attr-1,非null-attr-2,非null-attr -....) specific_type_country(country_id,非null-attr-1,非null-attr-2,非null-attr -...)

  3. 国家主表中的所有属性,只有在您不需要从系统向国家/地区添加新属性时,此方法才可行。例如:

    country(country_id,non-null-attr-1,non-null-attr-2,non-null-attr -....,nullable-attr-1,nullable-2,nullable-attr- .. 。)

  4. 当我在这种情况下进行设计时,我常常考虑在这些数据上运行的查询的性能。

    如果查询是所有可能属性的国家/地区列表,则使用No.3更好。

    如果查询针对特定类别的国家/地区,例如,国家/地区的列表具有最近的海洋(此属性不能为空)。 No.2更好。

    如果查询一次需要一个国家/地区的详细信息,则No.1更好。

    当然,您可以混合以上三种策略中的任何一种来为您的可能查询设计合适的解决方案。


    假设任何疑问都需要“最有名的食物”(可以为空),将此属性放入国家主表。

    假设在一些查询中需要“最近的海洋”,将此属性放入国家表的子类中。

    假设最多只检索一行的查询(例如,通过主键查询)需要“最高山名”,“最高山的平均温度”,将此属性放入元表中。