数据库规范化 - 字段取决于另一个非关键字段
Database Normalization - Field depending on another non-key field
以下是 SQL 服务器中 table 定义的一部分:
CREATE TABLE User
[UserId] INT NOT NULL IDENTITY(1,1),
[EatsFruit] BIT NOT NULL DEFAULT '0',
[FavoriteFruit] NVARCHAR(50) DEFAULT NULL,
可以想象,UserId是主键。我在这里使用了一个更简单的示例来解释我与 "fruit" 字段相关的问题。
EatsFruit 字段将为 1 或 0,具体取决于用户是否吃水果。如果 EatsFruit 包含 1,则 FavoriteFruit 字段将包含用户最喜欢的水果。如果 EatsFruit 为 0,则 FavoriteFruit 不相关,它必须包含 N/A 或一些类似的值。
我想知道对此建模的最佳方法是什么,是否需要对其进行标准化。
既然 FavoriteFruit 字段依赖于 EatsFruit 的内容,是否应该将其分隔在包含 UserId 和 FavoriteFruit 的不同 table 中?这会更简洁,因为除非用户实际吃水果(并且 FavoriteFruit 的内容总是相关的),否则不会出现某个用户的条目。但是,由于新 table 的主键也将是 UserId,这是否意味着 FavoriteFruit 确实依赖于 UserId,并且一开始就不应该与主 table 分开?
此处的最佳做法是什么?非常感谢!
当您开始在 table 中保存条件 NULL
时,您就知道数据需要标准化。
假设您的员工 table 中有一个字段 anual_bonus
,但只有经理才能获得奖金。您将在该字段中有很多空值,这将是一种浪费。
对于这种情况,我会
用户:
user_id
吃水果:
user_id
favorite_fruit_id (can be null if user eat fruit but doesnt have favorite?)
水果
fruit_id
fruit_name
所以要获得喜欢水果的用户你就
SELECT user.*
FROM user
LEFT JOIN EatFruit
on user.user_id = EatFruit.user_id
WHERE EatFruit.user_id IS NOT NULL
从纯粹的规范化角度来看,您不希望有一个字段可能会占用 space 无用的信息,就像在您的示例中用户不吃水果时那样。此外,您真的不希望 Favorite Fruit 成为 NVarchar,因为 "Melon" 和 "Watermelon" 是不同的东西(或者它们是不同的东西),或者 "Aple" 的意外条目呢?
如果是我,我会有一个水果 Table 和一个 FavoriteFruit 协会 table,FavoriteFruit table 会有水果 ID 和用户 ID。如果用户没有最喜欢的水果,则不使用 space。另外,我会问我是否可以去掉 "EatsFruit" 并简单地检查 FavoriteFruits table 中的条目。
话虽如此,你的这种套路,虽然可能玩得有点松散,但并不是不可饶恕的罪过。
干杯。
以下是 SQL 服务器中 table 定义的一部分:
CREATE TABLE User
[UserId] INT NOT NULL IDENTITY(1,1),
[EatsFruit] BIT NOT NULL DEFAULT '0',
[FavoriteFruit] NVARCHAR(50) DEFAULT NULL,
可以想象,UserId是主键。我在这里使用了一个更简单的示例来解释我与 "fruit" 字段相关的问题。
EatsFruit 字段将为 1 或 0,具体取决于用户是否吃水果。如果 EatsFruit 包含 1,则 FavoriteFruit 字段将包含用户最喜欢的水果。如果 EatsFruit 为 0,则 FavoriteFruit 不相关,它必须包含 N/A 或一些类似的值。
我想知道对此建模的最佳方法是什么,是否需要对其进行标准化。
既然 FavoriteFruit 字段依赖于 EatsFruit 的内容,是否应该将其分隔在包含 UserId 和 FavoriteFruit 的不同 table 中?这会更简洁,因为除非用户实际吃水果(并且 FavoriteFruit 的内容总是相关的),否则不会出现某个用户的条目。但是,由于新 table 的主键也将是 UserId,这是否意味着 FavoriteFruit 确实依赖于 UserId,并且一开始就不应该与主 table 分开?
此处的最佳做法是什么?非常感谢!
当您开始在 table 中保存条件 NULL
时,您就知道数据需要标准化。
假设您的员工 table 中有一个字段 anual_bonus
,但只有经理才能获得奖金。您将在该字段中有很多空值,这将是一种浪费。
对于这种情况,我会
用户:
user_id
吃水果:
user_id
favorite_fruit_id (can be null if user eat fruit but doesnt have favorite?)
水果
fruit_id
fruit_name
所以要获得喜欢水果的用户你就
SELECT user.*
FROM user
LEFT JOIN EatFruit
on user.user_id = EatFruit.user_id
WHERE EatFruit.user_id IS NOT NULL
从纯粹的规范化角度来看,您不希望有一个字段可能会占用 space 无用的信息,就像在您的示例中用户不吃水果时那样。此外,您真的不希望 Favorite Fruit 成为 NVarchar,因为 "Melon" 和 "Watermelon" 是不同的东西(或者它们是不同的东西),或者 "Aple" 的意外条目呢?
如果是我,我会有一个水果 Table 和一个 FavoriteFruit 协会 table,FavoriteFruit table 会有水果 ID 和用户 ID。如果用户没有最喜欢的水果,则不使用 space。另外,我会问我是否可以去掉 "EatsFruit" 并简单地检查 FavoriteFruits table 中的条目。
话虽如此,你的这种套路,虽然可能玩得有点松散,但并不是不可饶恕的罪过。
干杯。