2011-09-02 78 views
2

我有一个包含两个表的数据库:UsersCategoriesSQL中的可变长度int列

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 

这将返回每种类别的用户属于一个行。有可能只返回一行?

+1

第三张表是解决您的问题。至于你的查询,你应该看看'exist'和'in'。 http://msdn.microsoft.com/en-us/library/ms177682.aspx http://msdn.microsoft.com/en-us/library/ms188336.aspx –

+0

如果你有什么预期的查询输出有多个类别的用户?您在Where子句中没有使用CategoriesPerUser,因此最简单的方法是从查询中删除表。 –

+0

在您编辑的示例中,如果用户与多个类别相关联,则需要拨打电话以确定要返回哪个用户...可能与“SELECT TOP 1”一样简单。但不清楚你想要达到什么目的。 – Jamiec

回答

4

目前您有一对多的关系,也就是说类别可以与许多用户关联,但用户只能与一个类别关联。

您需要将其更改为多对多关系,以便每个用户都可以与多个类别关联,并且每个类别都可以与多个用户关联。

这是实现由(从用户表和删除类别ID)将其链接的用户ID和类别ID的表

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> 
) 
+0

感谢您的建议。这适用于查找某个类别中的所有用户的情况,但如果我试图根据其他某个搜索参数查找所有用户并希望返回用户所属的所有类别,则会出现问题。 – Oliver

+0

@Oliver - 查看更新。此外,*任何*可以找到正确的数据库结构。这*是您的需求的正确数据库结构。 – Jamiec

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 
0

由于这是一个N对N的关系(一类可以有多个用户,一个用户可以有几个类别),实现这一点的典型方法是建立一个联结表。

但正如你所说,你不想为已经实现的功能创建第三个表,我想你也可以将用户表中的列“CategoryId”更改为“CategorieIds”,然后它可以包含一个文本字段。该文本字段可以包含由特殊字符(例如“,”)分隔的整数列表。就我而言,你应该对你的实现代码做分割操作,因为我不知道在SQL中做这个的实际方法(也许有人可以在这里纠正我)。

你也可以让你的categoryId列,然后,如果你想实现像每个用户'主'类别的东西。

希望这会有所帮助,我希望能有一个正确的方法来实现这个!

+2

逗号分隔值在文本字段中让宝宝耶稣哭泣。 – Jamiec

+0

感谢您的评论,我想过要做这样的事情,但是对像这样的一串ID进行搜索可能会非常低效。 – Oliver

+0

是的,当然第三张桌子是最高性能的选择。如果由于某种原因,我真的不想为这种关系创建一个单独的表 - 我绝对同意Jamiecs的评论! –