两张表到一张表的关系

时间:2019-10-28 18:16:22

标签: database postgresql algorithm design-patterns

设计数据库的一部分以及它们之间的关系时遇到了麻烦。

我的实体是:

  • 车辆-> 1:1->价格
  • 自行车-> 1:1->价格

选项A:

创建2个表

车辆表

+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid    |
| brand          | varchar |
| model          | varchar |
| attribute1     | varchar |
| price          | float   |
| discount float |         |
| locale varchar |         |
+----------------+---------+

自行车桌

+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid    |
| vendor         | varchar |
| attribute1     | varchar |
| attribute2     | varchar |
| attribute3     | varchar |
| price          | float   |
| discount float |         |
| locale varchar |         |
+----------------+---------+

选项B

创建3个表

车辆表

+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid    |
| brand          | varchar |
| model          | varchar |
| attribute1     | varchar |
+----------------+---------+

自行车桌


+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid    |
| vendor         | varchar |
| attribute1     | varchar |
| attribute2     | varchar |
| attribute3     | varchar |
+----------------+---------+

价格表

+----------------+-------+
|      NAME      | TYPE  |
+----------------+-------+
| vehicle_id     | FK    |
| bike_id        | FK    |
| price          | float |
| discount float |       |
| locale varchar |       |
+----------------+-------+

选项C

创建4个表

车辆表

+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid    |
| brand          | varchar |
| model          | varchar |
| attribute1     | varchar |
+----------------+---------+

VEHICLES_PRICES表

+----------------+-------+
|      NAME      | TYPE  |
+----------------+-------+
| vehicle_id     | FK    |
| price          | float |
| discount float |       |
| locale varchar |       |
+----------------+-------+

自行车桌


+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid    |
| vendor         | varchar |
| attribute1     | varchar |
| attribute2     | varchar |
| attribute3     | varchar |
+----------------+---------+

BIKE_PRICES表

+----------------+-------+
|      NAME      | TYPE  |
+----------------+-------+
| bike_id        | FK    |
| price          | float |
| discount float |       |
| locale varchar |       |
+----------------+-------+

注意:我确实简化了车辆和自行车表(我无法将两者合并在一个表中,例如“产品”)

性能模式的角度来看,我们将是最好的设计?

3 个答案:

答案 0 :(得分:0)

我会选择选项B,因为您不能将两者合并。这样,您可以拥有多个价格和/或保留未来价格变化的记录。

答案 1 :(得分:0)

如果您可以将ID范围分为两部分(例如,自行车小于50000000,车辆大于50000000,请选择选项B。这样可以避免创建未使用的空列。
否则,选项C会为更改提供更好的灵活性,因为自行车和汽车所需的数据将来会有所不同。
还可以通过在价格表中添加其他DateTime列来保留价格历史记录。

答案 2 :(得分:0)

如果您需要将所有价格都放在一个表中(以进行排序等),那么选项B很好,尽管您可能希望对价格表进行约束,使每一行都精确地引用车辆或自行车,但两者都不是。

请注意,这里您可能拥有没有价格的车辆或自行车。

另一种方法是反转外键关系,并具有三个这样的表:

PRODUCTS TABLE
+----------------+---------+
|      NAME      | TYPE    |
+----------------+---------+
| product_id     | uuid    |
| price          | float   |
| discount       | float   |
| locale         | varchar |
+----------------+---------+
VEHICLES TABLE
+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid,FK |
| brand          | varchar |
| model          | varchar |
| attribute1     | varchar |
+----------------+---------+
BIKES TABLE
+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid,FK |
| vendor         | varchar |
| attribute1     | varchar |
| attribute2     | varchar |
| attribute3     | varchar |
+----------------+---------+

现在您可以拥有既不是自行车也不是车辆的产品,并且可以同时具有既不是自行车又不是车辆的产品。缺点是对于给定的产品,您不知道它是什么。

另一方面,该方案可以强制要求每辆车和每辆自行车都有价格。


由于您询问的是模式观点,因此从这方面出发,解决方案是使用composite type for your prices。价格不是一个实体(具有自己的标识),它只是自行车和车辆使用的一个值。这里我们只有两个表:

PRICE _TYPE_
+----------------+---------+
|      NAME      | TYPE    |
+----------------+---------+
| value          | float   |
| discount       | float   |
| locale         | varchar |
+----------------+---------+
VEHICLES TABLE
+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid,FK |
| brand          | varchar |
| model          | varchar |
| attribute1     | varchar |
| price          | price   |
+----------------+---------+
BIKES TABLE
+----------------+---------+
|      NAME      |  TYPE   |
+----------------+---------+
| Id             | uuid,FK |
| vendor         | varchar |
| attribute1     | varchar |
| attribute2     | varchar |
| attribute3     | varchar |
| price          | price   |
+----------------+---------+

这将与您的解决方案A等效,尽管代码重用性更高。此外,price字段现在可以作为完整结构而不是在其各个部分上为空。

但是,从性能和可用性的角度来看,我建议避免使用复合类型,使用它们很麻烦。您宁愿使用解决方案A,并手动保持与价格相关的列定义同步。