我的数据库中有三种类型的内容。它们是歌曲,专辑和播放列表。专辑和播放列表只是歌曲的集合。我想让用户为他们每个人都喜欢。我用列做了表
LikeId UserId SongId PlaylistId AlbumId
用于存储喜欢的内容。例如,如果用户喜欢歌曲,我将歌曲的id放入SongId列,将用户的id放入UserId列。其他列将为null。它运作良好,但我不喜欢这个解决方案,因为它没有正常化。 所以我想问一下是否有更好的解决方案。
答案 0 :(得分:0)
怎么样
LikeId UserId LikeType TargetId
LikeType可以是“歌曲”,“播放列表”还是“专辑”?
答案 1 :(得分:0)
你的解决方案很好。它具有很好的功能,您可以设置与其他表的显式外键关系。此外,您可以通过添加检查约束来验证是否设置了其中一个值:
check ((case when SongId is null then 0 else 1 end) +
(case when AlbumId is null then 0 else 1 end) +
(case when PlayListId is null then 0 else 1 end)
) = 1
为所有三个值存储NULL
值会产生开销。这三个值相当小。
您甚至可以添加计算列以获取存储的值:
WhichId = (case when SongId is not null then 'Song'
when AlbumId is not null then 'Album'
when PlayListId is not null then 'PlayList
end);
答案 2 :(得分:0)
作为惩罚的贪婪,我会使用三个表:UserLikesSongs,UserLikesPlaylists和UserLikesAlbums。每个包含一个UserId和对其他表之一的适当引用:歌曲,专辑或播放列表。
这还允许添加其他类型特定信息。也许专辑将来会支持最喜欢的曲目。
您始终可以使用UNION组合各种实体类型的数据。
答案 3 :(得分:0)
您应该只创建3个表 - 一个用户与播放列表,歌曲和专辑中的每一个配对。它们看起来像是:
CREATE TABLE PlaylistLikes
(
UserID INT NOT NULL,
PlaylistID INT NOT NULL,
PRIMARY KEY (UserID, PlaylistID),
FOREIGN KEY (UserID) REFERENCES Users (UserID),
FOREIGN KEY (PlaylistID) REFERENCES Playlists (PlaylistID)
);
CREATE TABLE SongLikes
(
UserID INT NOT NULL,
SongID INT NOT NULL,
PRIMARY KEY (UserID, SongID),
FOREIGN KEY (UserID) REFERENCES Users (UserID),
FOREIGN KEY (SongID) REFERENCES Songs (SongID)
);
CREATE TABLE AlbumLikes
(
UserID INT NOT NULL,
AlbumID INT NOT NULL,
PRIMARY KEY (UserID, AlbumID),
FOREIGN KEY (UserID) REFERENCES Users (UserID),
FOREIGN KEY (AlbumID) REFERENCES Albums (AlbumID)
);
在这里,主键中的两列都可以防止用户多次喜欢歌曲/播放列表/专辑(除非您希望它可用 - 然后删除它或者可能会跟踪一些喜欢的内容) '专栏)。
你应该避免将所有3种不同类型的喜欢放在同一张表中 - 应该使用不同的表来表示不同的东西。你想避免“一个真正的查询表” - 这里有一个答案,详细说明原因:OTLT
如果要查询所有3个表,可以创建一个视图,该视图是3个表之间UNION的结果。