SQL中的可变长度int列

时间:2011-09-02 09:13:13

标签: sql-server

我有一个包含两个表的数据库:UsersCategories

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

这将为用户所属的每个类别返回一行。它可以只返回一行吗?

3 个答案:

答案 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。

希望这有帮助,我希望建议一个正确的方法来实现这个!