【发布时间】:2018-06-09 04:44:07
【问题描述】:
想象一下网上商店。你有货。有些商品有尺寸,有些没有。我有一个orders 表:
id int not null,
...
orders_products表:
order_id int not null,
product_id int null,
size_id int null,
...
products表:
id int not null,
...
sizes表:
id int not null,
product_id int not null,
...
现在product_id 或size_id 不为空。换句话说,主键是order_id + (product_id xor size_id)。两者都不是。
用 Django 的话来说是:
class OrderProduct(models.Model):
product = models.ForeignKey(Product, null=True, on_delete=models.CASCADE)
size = models.ForeignKey(Size, null=True, on_delete=models.CASCADE)
order = models.ForeignKey('Order', on_delete=models.CASCADE)
amount = models.PositiveSmallIntegerField()
class Order(models.Model):
products = models.ManyToManyField(Product, through=OrderProduct, related_name='orders')
sizes = models.ManyToManyField(Size, through=OrderProduct, related_name='orders')
...
至少这是我现在所拥有的。但我不喜欢在orders_products 表中有两个互斥的外键。或Order 模型中的两个属性。其中之一 (sizes) 可能是多余的。
所以,我可能必须从 Order 模型中删除 sizes 属性。是这样吗?或者我应该让product_id 在orders_products 表中不为空?并且只有当产品有不同尺寸时才有size_id?还有其他建议吗?
我用django、python、postgresql 标记了这个问题。那是因为这些是我现在正在使用的。但我不拘泥于任何特定的语言,而是 SQL。
UPD 我刚刚意识到我已经对 sizes 表进行了非规范化。那里主要有S、M、L 尺寸。
现在我看到四个选项:
我现在的样子。
Order.products和Order.sizes似乎有效。他们得到不相交的产品集。但是数据库中存在不一致的可能性(orders_products.product_id和orders_products.size_id都已设置或未设置)。建议maverick:通用外键。
-
规范化
sizes表(多对多关系):products表:id int not null, ...products_sizes表:product_id int not null, size_id int not null, ...sizes表:id int not null, ...然后,以这种方式拥有
orders_products表:order_id int not null, product_id int null not null, size_id int null, ...有点意思。好吧,对于具有尺寸的产品,
orders_products.size_id仍有可能为空。对于orders_products.size_id被链接到产品没有的尺寸。通用外键不太可能在规范化表的情况下使用。
-
提取
product_variants表(消费者基本买的):products:id int not null, ...sizes:id int not null, ...product_variants:id int not null, product id int not null, size_id int nullorders_products:order_id int not null, productvariant_id int not null, amount int not null关于通用外键的说法似乎也适用于此。
哪个更好?
【问题讨论】:
标签: python sql django postgresql many-to-many