Как спроектировать базу данных, используя различное количество столбцов в таблице - PullRequest
3 голосов
/ 24 февраля 2012

Допустим, вы создаете систему для хранения характеристик разных стран. Там будут те же основные столбцы, как имя, население, столица и т. Д. Но, скажем, в дополнение к этому вы хотите хранить некоторую информацию о конкретной стране, такую ​​как самая высокая гора, ближайший океан, самая известная еда и т. Д. страна.

Как это можно сделать с помощью реляционной базы данных, такой как MySQL. Я знаю, что это проще использовать безсхемную базу данных NoSQL, такую ​​как MongoDB, где каждая страна может храниться как отдельный документ. Но можно ли что-то подобное сделать с помощью реляционных БД?

Ответы [ 8 ]

4 голосов
/ 24 февраля 2012

Только с текстовыми полями вам нужны две дополнительные таблицы:

  • свойства (содержит имя свойства, например, "самая высокая гора")
  • country_properties (содержит значения для страныпары свойств: например: идентификатор страны "austria", идентификатор свойства "самая высокая гора", "имя горы")

В качестве альтернативы, если существует только несколько свойств, просто сохраните NULLдля неизвестных значений.

3 голосов
/ 24 февраля 2012

Может. Как я узнал сегодня, задав другой вопрос по SO , он называется EAV (для модели Entity-Attribute-Value). Я нашел интересное объяснение об этом в Википедии .

0 голосов
/ 25 февраля 2012

Здесь у нас есть три стратегии:

  1. Полно-мета-дизайн, значения атрибутов, допускающих значения NULL для стран, будут занесены в таблицу сбора значений.Например:

    страна (country_id, ненулевой attr-1, ненулевой attr-2, ненулевой attr -....) meta_attr (attr_id, attr_desc) (может быть более сложнойесли вам нужен I18N) attr_value (country_id, attr_id, attr_value)

  2. Частично мета-дизайн, используя подкласс таблицы для ссылки на основную таблицу страны.Такой метод можно использовать, если вы можете классифицировать определенный экземпляр данных в коллекцию ненулевых атрибутов.Например:

    страна (country_id, ненулевой attr-1, ненулевой attr-2, ненулевой attr -....) specific_type_country (country_id, ненулевой attr-1, non-null-attr-2, non-null-attr -...)

  3. Все атрибуты в основной таблице стран, этот метод является жизнеспособным, только если вы ненужно добавить новый атрибут в страну из системы.Например:

    страна (country_id, ненулевое attr-1, ненулевое attr-2, ненулевое attr -...., nullable-attr-1, nullable-2,nullable-attr -...)

Когда я проектировал по такому сценарию, я обычно учитывал производительность запросов, выполняющихся на таких данных.

Если запросысписок стран для всех возможных атрибутов, лучше использовать № 3.

Если запросы относятся к определенным классам стран, скажем, список стран имеет ближайший океан (что этот атрибут не может бытьноль).№ 2 лучше.

Если для запросов требуется подробная информация о стране за один раз, № 1 лучше.

Конечно, вы можете смешать любую из трех вышеуказанных стратегий, чтобыразработайте подходящее решение для ваших возможных запросов.


Предположим, что для самых разных запросов потребуется «самая известная еда» (nullable), поместите этот атрибут в основную таблицу страны.

Предположим, что "ближайший океан" необходим в нескольких запросах, поместите этот атрибут в подкласс таблицы стран.

Предположим, что "название самой высокой горы", "Средняя температура самой высокой горы"необходим для запросов, которые получают только одну строку (скажем, по первичному ключу), поместите этот атрибут в мета-таблицу.

0 голосов
/ 24 февраля 2012

То, что вы описываете, является Супертипом * Подтипом * структуры данных. Super-Type является общим для всех данных (в вашем случае стран). Подтип является уникальным для каждой группы данных (в ваших странах). У вас будет одна таблица супертипа ** и ** несколько таблиц подтипа . Таблицы подтипов содержат FKeys, которые ссылаются на таблицу супертипов.

Это позволяет запрашивать все по супертипу , а затем выполнять детализацию по подтипу .

* сильный текст * Подтипы, которые приходят на ум для стран:
Mountanous
* 1023 имеет выхода к морю * OceanView

Вы можете даже выделить их по континентам: Северная Америка
* 1027 Южная Америка * Азия
Океания

0 голосов
/ 24 февраля 2012

Давайте возьмем горы в качестве примера:

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;
0 голосов
/ 24 февраля 2012

У меня похожий сценарий с приложением, требующим 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 - это ссылка для вас, чтобы вывести данные, так что это может быть, например, «население»и country_data будет иметь фактические данные, которые вы хотите.

Затем вы используете JOIN, и в каждой строке будут все необходимые данные.Это самая гибкая структура с использованием MySQL, которую я знаю, и она хорошо работает для задач такого типа.

Надеюсь, это поможет.

0 голосов
/ 24 февраля 2012

Если столбцы действительно разные для каждой страны, то создайте новую таблицу с именем country_field со следующими столбцами

  • country_id (FK для таблицы вашей страны)
  • field_name varchar
  • field_value varchar

Сохраните атрибуты вашей страны в этой таблице с одной строкой для каждого поля, специфичного для страны.

0 голосов
/ 24 февраля 2012

Вы действительно не должны делать это со стандартной реляционной базой данных.Вместо этого храните дополнительные данные в отдельных таблицах и используйте внешний ключ, ссылающийся на таблицу стран.

Наличие столбцов, которые используются только иногда, обычно является нарушением реляционной целостности.Иногда это необходимо по соображениям производительности, но если это вас не касается, я настоятельно рекомендую использовать наиболее подходящую модель отношений.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...