Элементы и специализированные элементы: несколько таблиц с дублирующимися столбцами, основная таблица и таблица сведений или ...? - PullRequest
5 голосов
/ 06 марта 2012

Мне нужно хранить данные, относящиеся к «элементам», где будут различные типы элементов, все с общими атрибутами, а затем каждый тип со своими дополнительными атрибутами. Я ожидаю, что это общее требование; какое решение для лучших практик? Мы используем SQL Server.

Давайте рассмотрим пример:

Автомобиль имеет

  • Цена
  • 1012 * Марка *
  • Модель
  • Владелец

(В наших реальных данных будет 10-15 общих столбцов.)

Автомобиль Автомобиль плюс:

  • Стиль (седан, спорт и пр.)
  • Цвет
  • EngineSize

Лодка Транспортное средство плюс:

  • Объем
  • PortOfOrigin

... и т.д.. для нескольких типов вещей. В наших реальных данных каждый специализированный тип обычно добавляет 2-5 столбцов; будет 5 типов для начала. Мы будем добавлять типы с течением времени, но, вероятно, всего на 3 или 4 больше (если это так). Добавление типов требует разработки, поэтому это не похоже на «теги», которые могут быть добавлены конечными пользователями. Мы предполагаем, что добавление типа потребует изменений в уровне БД и клиента, а также, возможно, и среднего уровня. Это совершенно нормально.

Мы сделаем множество запросов по всем пунктам (транспортные средства, в приведенном выше примере); мы редко беспокоимся о деталях определенного типа предмета (автомобиль, лодка).

Я вижу четыре способа хранения этих данных:

  1. Отдельные таблицы для автомобилей, лодок и т. Д. С дублированными столбцами.
  2. Одна таблица с данными Vehicle, таблица для дополнительных данных Car и таблица для дополнительных данных Boat.
  3. Одна таблица элементов, отдельная таблица атрибутов элементов со строкой для каждого дополнительного атрибута. Например, мягкая схема для деталей.
  4. Одна таблица с общими столбцами, имеющими значение только для кода, не относящегося к БД.

Глядя на каждого:

  1. Отдельные таблицы для автомобилей, лодок и т. Д. С дублированными столбцами. Например, примерно:

    CREATE TABLE [Cars] (
        [Id] IDENTITY PRIMARY KEY,
        [Price] DECIMAL (19, 4),
        [Make] NVARCHAR(200),
        [Model] NVARCHAR(200),
        [Owner] INT,
        [Id] INT PRIMARY KEY,
        [Style] NVARCHAR(200),
        [Color] NVARCHAR(200),
        [EngineSize] DECIMAL(19, 2)
    )
    CREATE TABLE [Boats] (
        [Id] IDENTITY PRIMARY KEY,
        [Price] DECIMAL (19, 4),
        [Make] NVARCHAR(200),
        [Model] NVARCHAR(200),
        [Owner] INT,
        [Id] INT PRIMARY KEY,
        [Displacement] DECIMAL(19, 4),
        [PortOfOrigin] NVARCHAR(200)
    )
    

    Достаточно просто, машины идут в Cars, а лодки идут в Boats. Если мы добавим больше типов транспортных средств, мы добавим таблицу. Если мы добавим еще один общий столбец, мы должны вернуться и добавить его во все таблицы транспортных средств. Отчетность по транспортным средствам в целом может быть получена в объединенном представлении всех таблиц (будьте осторожны с колонкой Id).

  2. Одна таблица с данными Vehicle, таблица для дополнительных данных Car и таблица для дополнительных данных Boat. Например, примерно:

    CREATE TABLE [Vehicles] (
        [Id] IDENTITY PRIMARY KEY,
        [Price] DECIMAL (19, 4),
        [Make] NVARCHAR(200),
        [Model] NVARCHAR(200),
        [Owner] INT,
        [Type] INT        -- A type ID, e.g. "Car" vs. "Boat"
    )
    CREATE TABLE [Cars] (
        [Id] INT PRIMARY KEY,
        [Style] NVARCHAR(200),
        [Color] NVARCHAR(200),
        [EngineSize] DECIMAL(19, 2)
    )
    CREATE TABLE [Boats] (
        [Id] INT PRIMARY KEY,
        [Displacement] DECIMAL(19, 4),
        [PortOfOrigin] NVARCHAR(200)
    )
    

    Таким образом, у каждого автомобиля будет одна строка в Vehicles и одна связанная строка в Cars. Каждая лодка будет иметь один ряд в Vehicles и один связанный ряд в Boats. Если мы добавим больше типов транспортных средств, мы добавим таблицу. Отчетность по транспортным средствам в целом может быть сделана только по таблице Vehicle. При получении сведений о конкретном Car или Boat мы используем соединение.

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

    CREATE TABLE [Vehicles] (
        [Id] IDENTITY PRIMARY KEY,
        [Price] DECIMAL (19, 4),
        [Make] NVARCHAR(200),
        [Model] NVARCHAR(200),
        [Owner] INT,
        [Type] INT
    )
    CREATE TABLE [VehicleDetails] (
        [VehicleId] INT,
        [Name] NVARCHAR(200),
        [Value] NVARCHAR(MAX)
    )
    

    Таким образом, каждый автомобиль получает одну строку в Vehicles и три строки в VehicleDetails (по одному для "Style", "Color" и "EngineSize"). Отчетность в основном делается на основе таблицы Vehicle. Отчетность по деталям быстро становится грязной. Мягкие схемы имеют свое место, в основном вокруг пользовательских данных, но я предполагаю, что это не будет хорошим выбором здесь.

  4. Одна таблица с общими столбцами, имеющими значение только для кода без БД:

    CREATE TABLE [Vehicles] (
        [Id] IDENTITY PRIMARY KEY,
        [Price] DECIMAL (19, 4),
        [Make] NVARCHAR(200),
        [Model] NVARCHAR(200),
        [Owner] INT,
        [Type] INT,
        [Detail01] NVARCHAR(MAX),
        [Detail02] NVARCHAR(MAX),
        [Detail03] NVARCHAR(MAX),
        [Detail04] NVARCHAR(MAX),
        [Detail05] NVARCHAR(MAX),
        [Detail06] NVARCHAR(MAX),
        [Detail07] NVARCHAR(MAX),
        [Detail08] NVARCHAR(MAX),
        [Detail09] NVARCHAR(MAX),
        [Detail10] NVARCHAR(MAX)
    )
    

    Таким образом, данные Car назначат Style для Detail01, Color для Detail02 и EngineSize для Detail03; для лодок мы поместили бы Displacement в Detail01 и PortOfOrigin в Detail02. Точно так же может быть место для этого с определенными пользователем схемами, но я предполагаю, что это не будет хорошим ответом, когда вы можете управлять структурой БД.

1 Ответ

6 голосов
/ 06 марта 2012

Это зависит.

Подход 1 лучше всего подходит для ситуаций, когда большинство атрибутов будет общим для большинства типов.

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

Подход 3 по существу является подходом 1 с подходом Entity-Attribute-Value для обработки атрибутов, специфичных для типа. Этот подход лучше всего подходит для ситуаций, когда большинство атрибутов будет общим для большинства типов, и трудно предугадать, какие дополнительные атрибуты потребуются, - это довольно часто в ситуациях, когда требуются поля, созданные пользователем.

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

Существует также другой возможный подход - чистый Entity-Attribute-Value подход (по сути, смесь подходов 3 и 4). Обычно это рассматривается как анти-шаблон из-за сложности и низкой производительности, создаваемой при реализации в СУБД. Однако в некоторых ситуациях это единственный возможный подход - прежде всего, когда отношения сущностей не известны заранее.

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