【问题标题】:Normalization and Tables in MySqlMySql 中的规范化和表
【发布时间】:2021-07-03 07:53:52
【问题描述】:

我知道以下问题可能是“基于意见的”,但由于我正在创建我的第一个 DBMS,所以我需要建议。

我有一个包含以下列的“订阅”表:

IDSubscription_PK, Date_Subscription, Cost_Subscription.

订阅费用根据订阅月份而有所不同(例如-> 3 个月:30 美元,6 个月:60 美元,依此类推,从 1 到 12 个月)

知道我在追求第三范式,你会建议我创建两个单独的表,像这样:

Subscription -> IDSubscription_PK, Date_Subscription, Months_Subscription
Costs -> Months_Subscription, Cost

所以,我将拥有:

SUBSCRIPTION_TABLE                |    COST_TABLE
IDSub.   Date.        Months.     |. Months.  Cost
2992.   2019/07/12.    1          |.  1.       10
9178.   2020/01/11.    10         |.  2.       20
1827.   2020/03/21.    7          |.  ...     ....
1928.   2020/11/10.    1          |.  12.      120

或者,一个单独的,如下:

Subscription -> IDSubscription_PK, Date_Subscription, Date_end_Subscription, cost

等等:

SUBSCRIPTION_TABLE              
IDSub.   Date.        EndOfSub    Cost 
2992.   2019/07/12.   2019/08/12   10
9178.   2020/01/11.   2020/11/11   100    
1827.   2020/03/21.   2020/10/21   70   
1928.   2020/11/10.   2020/12/10   10       

【问题讨论】:

标签: mysql sql sql-server database database-design


【解决方案1】:

不管subscription表的细节如何,都需要把实际的成本放到用户表中。明天,您可能会更改费率。因此,您应该让用户表指向订阅表。

或者……

订阅表可以有一个应用天数。当您更改价格时,您会在该表中添加新行。新(或续订)订阅将链接到新行。但是……这个模型实现起来很麻烦;我更喜欢另一种方法。

【讨论】:

    【解决方案2】:

    我建议您添加cost 表。为什么?

    如果没有它,您将不得不对subscription 表执行某种SELECT DISTINCT 操作以获取价目表。如果某些订户有独特的交易,那可能会产生垃圾。一般来说,如果你必须通过SELECT DISTINCT 或类似的方式来获取你需要的信息,这是非规范化的标志。

    更好的是,我建议 plan 代替您的 cost 表。

    它将包含这些类型的条目

    plan_id   months  cost  description
       1        1      10   Monthly plan
       2        1       5   Monthly plan, student discount
       3       12     100   Yearly plan
       4       12      35   Yearly plan, student discount
    

    这使您可以灵活地根据业务需要以表格驱动而不是逻辑驱动的方式调整价格。

    然后,您的subscription 表将如下所示。

    subscription_id  plan_id subscriber_id renewal_date 
       1                1       101         2020-05-05
       2                4       103         2021-04-05
    

    而且,很容易获得您的价目表:SELECT * FROM plan

    专业提示:避免在表名和列名中混合使用大小写。当服务器托管在不同的操作系统上时,MySQL 的区分大小写规则是不同的,您现在或将来都不想处理这个问题。全部小写:没问题。

    专业提示:通常为表中的实体命名表,如plansubscription。然后,将表的自增 PK 命名为 plan_idsubscription_idwhatever_id。当您在其他表中使用与 FK 相同的 id 时,请为其使用相同的 whatever_id 名称。对于将来必须阅读和维护您的 SQL 的人来说,这使得生活更加更轻松。

    【讨论】:

    • 很清楚,谢谢!我有两个问题:在“订阅表”中,“subscription_id”代表什么? (因为我看到两个相等的数字)第二个:为什么“计划表”比我在示例中输入的“成本表”更受欢迎(因为学生没有折扣或类似的东西,我会有 12 个不同的计划(1个月、2个月...12个月)
    • 两个相同的subscription_id 值是我的错误。固定的;感谢您指出。 plan 表不要求您拥有多个订阅计划,但它确实允许您这样做。我认为使用几个月作为成本指针没有多大意义。它根本不是很灵活。这是根据我运行真正订阅服务的经验得出的,每年的收入约为 100 万美元。
    • 所以我可以创建两个表:CUSTOMER 和 PLAN,以及第三个表(关联实体),其主键是 PlanID、CustomerID 和 Date? (“日期”也应该是一个PK,因为同一个客户可以多次订阅同一个计划,所以也应该有日期作为标识符)你认为这是一个很好的解决方案吗?
    • 或者,第三个表可能有一个特定的 PK(例如,订阅 ID),而 PlanID 是作为外键的客户 ID。这个解决方案还是以前的解决方案?
    猜你喜欢
    • 2013-08-21
    • 2018-06-06
    • 2012-04-19
    • 2013-01-08
    • 1970-01-01
    • 2014-09-23
    • 2012-03-16
    • 2014-07-09
    • 2012-09-08
    相关资源
    最近更新 更多