我有一个包含两个表的数据库:Users
和Categories
。
Users
包含以下字段:
UserId unique identifier
UserName nvarchar
CategoryId int
Categories
包含以下字段:
CategoryId int
CategoryName nvarchar
目前,每个用户都属于一个类别。我想更改此设置,以便每个用户可以处于任意数量的类别。这样做的最佳方式是什么?
我的网站进行了大量非常昂贵的搜索,因此解决方案需要尽可能高效。我真的不想把每个用户的类别列表放在第三个表中,因为这意味着当我撤回搜索时,每个用户将同时表示几行(至少,这是会发生什么)如果我用我当前的,相当粗略的,对sql的理解来实现搜索。)
编辑:
如果设置多对多关系,是否可以为每个用户只返回一行?
例如:
DECLARE @SearchUserID nvarchar(200) = 1;
SELECT *
FROM Users JOIN Categories JOIN CategoriesPerUser
WHERE UserId = @SearchUserID
这将为用户所属的每个类别返回一行。它可以只返回一行吗?
答案 0 :(得分:4)
目前您有一对多的关系,也就是说类别可以与许多用户相关联,但用户只能与一个类别相关联。
您需要将此更改为多对多关系,以便每个用户可以与多个类别关联,并且每个类别都可以与许多用户关联。
通过添加链接用户标识和类别标识的表(以及从用户表中删除categoryid)来实现这一目标
Table: UserToCategory
UserId int
CategoryId int
至于你的最后一段,这个是最有效的需求建模方式。您应该将UserId / CategoryId组合在此表中的PrimaryKey,以阻止用户与同一类别关联两次。这样可以解决用户针对特定类别返回两次的问题。
例如,要查找与类别关联的所有用户的SQL将是
SELECT u.*
FROM Users u
INNER JOIN UserToCategory uc
ON u.UserId = uc.UserID
WHERE uc.CategoryId = 123
评论后编辑:如果您的查询找到了许多用户,并且您想要与这些用户关联的不同类别列表,则可以这样做
SELECT c.*
FROM Categories c
WHERE CategoryId IN
(
SELECT uc.CategoryID
FROM UserToCategory uc
INNER JOIN Users u ON uc.UserId = u.UserID
WHERE <some criteria here to filter users>
)
答案 1 :(得分:1)
我会将CategoryId从用户中删除并转到3d表:
UserCategories
- UserId
- CategoryId
如果要搜索用户的所有类别,可以使用例如:
SELECT uc.CategoryId, c.CategoryName
FROM UserCategories uc
JOIN Categories c ON uc.CategoryId = c.CategoryId
WHERE uc.UserId = @UserId
答案 2 :(得分:0)
由于这是一个n对n关系(一个类别可以有多个用户,一个用户可以有多个类别),实现这一点的典型方法是拥有一个联结表。
但正如你所说,你不想因为已经实现的功能而创建第三个表,我想你也可以将User表中的“CategoryId”列改为“CategorieIds”,然后可以包含一个文本域。此文本字段可以包含整数列表,由特殊字符(例如“,”)分隔。就我而言,你应该对你的实现代码进行拆分操作,因为我不知道在sql中做任何实际的方法(也许有人可以在这里纠正我......)。
如果你想为每个用户实现类似“主要”类别的东西,你也可以保留categoryId Column。
希望这有帮助,我希望建议一个正确的方法来实现这个!