变量列名的数据库设计

时间:2011-03-13 11:35:15

标签: ruby-on-rails ruby-on-rails-3

我的情况涉及编写项目报告的公司,项目和员工。

公司拥有许多项目,许多报告和许多员工 一份报告是由一名员工为公司的一个项目撰写的。

公司在报告中都需要不同的东西。假设有一家公司希望了解项目绩效和速度,而另一家公司想了解成本效益。有5-15个标准,每个公司设置不同,所有标准都适用于该公司的所有项目报告。

我正在考虑采用不同的方法,但我目前的僵局是:

  • 要在公司表格中添加文字字段criteria,其中包含按顺序排列的所需条件数组。
  • 在报告表格中,有一个company_id和一列criterion1criterion2等。

我完全清楚这通常被认为是可怕的数据库设计 - 不优雅且不灵活。所以,我需要你的帮助!我怎样才能更好地建立这个?


结论

由于以下原因,我决定使用序列化选项:

  1. 我对标准的要求很简单 - 每个员工提交报告后,不需要对报告进行搜索或排序。
  2. 我想最大限度地减少数据库负载 - 将要实现这些目标,已经存在一个带有开销的大页面。
  3. 我想避免使我的数据库结构复杂化,因为我认为这是一个相对简单的需求。
  4. CouchDB和Mongo目前不在我的保留节目中,所以我会将它们保存在更有需要的日子。

3 个答案:

答案 0 :(得分:3)

这将是使用NoSQL的绝佳机会!看起来像教科书用例对我来说。所以请转到CouchDBMongo并开始黑客攻击。

对于传统的数据库,您会轻微地了解数据规范化的问题:

  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. 变量列(例如crit1crit2等)。

    我强烈建议不要这样做。你没有获得太多的好处(因为你不知道你的信息在哪一列,它仍然不是很容易搜索)并且它导致可维护性的噩梦。想象一下,你的数据库获得了几百万条记录,突然有人需要16个标准。本来可以完全没有问题的是突然迁移,为数百万条记录增加了一个完全没用的字段。

    另一个问题是很多ActiveRecord魔法都无法解决这个问题 - 你必须自己弄清楚crit1的含义 - 现在如果你不想在这些字段上添加验证,那么这增加了许多毫无意义的工作。

  4. 总结一下:看一下Mongo或CouchDB,如果这看起来不切实际,请继续保存你的东西serialized。如果您需要进行复杂的验证并且不太关心数据库负载,那么请将其标准化并选择选项1.

答案 1 :(得分:0)

创建一个criteria表,其中列出了每家公司的条件(company 1 .. * criteria)。

然后,创建一个report_criteria表(report 1 .. * report_criteria),根据criteria表({{1}列出该特定报告的条件1 ... * criteria)。

答案 2 :(得分:0)

好吧,当你说“到公司表时,添加文本字段标准,其中包含一系列所需的标准”,闻起来像公司表想要规范化:你可以在15中的一个中打破每个标准名为“criterion1”,...,“criterion15”的列,其中任何或所有列都可以默认为null。

对我而言,您与报告表一起走在正确的轨道上。该表中的每一行可能代表一个报告;并且可能有相应的列“criterion1”,...,“criterion15”,正如您所说,每个单元格表示公司在该列标准上的表现。每个公司将有多个报告,因此您需要在报告表中显示日期(或报告编号或类似)列。然后日期加上公司ID可以是复合键;并且公司ID可以是非唯一索引。报告日期/号码/某些标识符也是如此。并且不要忘记报告员工ID的列。

报告表中的任何和每个标准列都可以为空,这意味着(可能)员工没有报告此标准;或者该标准(专栏)不适用于本报告(行)。

看起来这样可以正常工作。我没有看到你需要加入。它看起来非常简单,至少对于这些天真无知的眼睛来说。