2011-09-02 76 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的評論! –