Проект базы данных для имен переменных столбцов - PullRequest
2 голосов
/ 13 марта 2011

У меня есть ситуация, в которой участвуют компании, проекты и сотрудники, которые пишут отчеты о проектах.

Компания владеет многими проектами, многими отчетами и многими сотрудниками.
Один отчет написан одним сотрудникомдля одного из проектов компании.

Компании хотят, чтобы в отчете были разные вещи.Допустим, одна компания хочет знать о производительности и скорости проекта, а другая хочет знать об эффективности затрат.Есть 5-15 критериев, по-разному устанавливаемых каждой компанией, которые ВСЕ применимы ко всем отчетам по проектам этой компании.

Я думал о разных способах сделать это, но мой нынешний тупик таков:

  • В таблицу компаний добавьте текстовое поле criteria, которое содержит массив критериев, требуемых по порядку.
  • В таблице отчета есть company_id и столбцы criterion1,criterion2 и т. Д.

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


Заключение

Я решил использовать сериализованную опцию в моем случае по следующим причинам:

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

Ответы [ 3 ]

3 голосов
/ 13 марта 2011

Это была бы прекрасная возможность использовать NoSQL!Похоже, учебник для меня.Так что зайдите на CouchDB или Mongo и начните взламывать.

С обычными БД вы слегка попадаете впроблема того, насколько нормализовать ваши данные:

  1. Некий «хороший» способ (то есть очень нормализованный) будет выглядеть примерно так:

    class Company < AR::Base
      has_many :reports
      has_many :criteria
    end
    
    class Report < AR::Base
      belongs_to :company
      has_many :criteria_values
      has_many :criteria, :through => :criteria_values
    
    end
    
    class Criteria < AR::Base # should be Criterion but whatever
      belongs_to :company
      has_many :criteria_values
      # one attribute 'name' (or 'type' and you can mess with STI)
    end
    
    class CriteriaValues < AR::Base
      belongs_to :report
      belongs_to :criteria
      # one attribute 'value'
    end
    

    Это делаетчто-то очень простое и быстрое в NoSQL - тройное или четырехкратное объединение в SQL, и у вас есть много моделей, которые практически ничего не делают.

  2. Другим способом является денормализация:

    class Company < AR::Base
      has_many :reports
      serialize :criteria
    end
    
    class Report < AR::Base
      belongs_to :company
      serialize :criteria_values
    
      def criteria
        self.company.criteria
      end
      # custom code here to validate that criteria_values correspond to criteria etc.
    end
    

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

    Хороший плагин, который реализует это Flag Shih Tzu который я использовал в нескольких проектах и ​​мог бы порекомендовать.

  3. Переменные столбцы (например, crit1, crit2 и т. д.).

    Iнастоятельно советую против этого.Вы не получаете большой выгоды (это все еще не очень доступно для поиска, так как вы не знаете, в какой колонке находится ваша информация), и это ведет к кошмарам удобства обслуживания.Представьте, что ваша БД получает несколько миллионов записей, и вдруг кому-то нужно 16 критериев.То, что могло бы быть совершенно беспроблемным, это внезапная миграция, которая добавляет совершенно бесполезное поле к миллионам записей.

    Другая проблема заключается в том, что большая часть магии ActiveRecord не работает с этим - вам придется самостоятельно выяснить, что означает crit1 - теперь, если вы не хотите добавлять проверки в эти полятогда это добавляет много бессмысленной работы.

Итак, подведем итог: взгляните на Mongo или CouchDB и, если это кажется непрактичным, продолжайте и сохраните ваши вещи serialized .Если вам нужно выполнить сложную проверку и не слишком беспокоиться о загрузке БД, нормализуйтесь и выберите вариант 1.

0 голосов
/ 13 марта 2011

Хорошо, когда вы говорите «В таблицу компаний, добавьте критерии текстового поля, которые содержат массив критериев, требуемых по порядку», который пахнет так, будто таблица компании хочет нормализоваться: вы можете разбить каждый критерий в одном из 15 столбцы с именем "criterion1", ..., "criterion15", где любой или все столбцы могут по умолчанию иметь значение null.

Для меня вы на правильном пути с таблицей отчетов. Каждая строка в этой таблице может представлять один отчет; и, как вы говорите, может иметь соответствующие столбцы «критерий1», ..., «критерий15», где каждая ячейка говорит о том, насколько хорошо компания справилась с критерием этого столбца. В каждой компании будет несколько отчетов, поэтому вам понадобится столбец с датой (или номером отчета или подобным) в таблице отчетов. Тогда дата плюс идентификатор компании могут быть составным ключом; и идентификатор компании может быть неуникальным индексом. Как и в отчете дата / номер / некий идентификатор. И не забудьте столбец для идентификатора сотрудника, который сообщает.

Любой и каждый столбец критерия в таблице отчета может быть нулевым, что означает (возможно), что сотрудник не отчитался по этому критерию; или что этот критерий (столбец) не применяется в данном отчете (строка).

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

0 голосов
/ 13 марта 2011

Создайте таблицу criteria, в которой перечислены критерии для каждой компании (company 1 .. * criteria).

Затем создайте таблицу report_criteria (report 1 ..* report_criteria), в котором перечислены критерии для этого конкретного отчета на основе таблицы criteria (criteria 1 .. * report_criteria).

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