2010-05-19 79 views
4

我有一張表,其記錄表示某些對象。爲了簡單起見,我假定表格只有一列,並且這是唯一的ObjectId。現在我需要一種方法來存儲該表中的對象組合。這些組合必須是唯一的,但可以是任意長度的。舉例來說,如果我有ObjectId小號如何將事物組合映射到關係數據庫?

1,2,3,4 

我想存儲以下組合:

{1,2}, {1,3,4}, {2,4}, {1,2,3,4} 

的排序是沒有必要的。我目前的實施是有一個表Combinations,它將ObjectId s映射到CombinationId s。因此,每個組合都會收到一個唯一的ID:

ObjectId | CombinationId 
------------------------ 
1  | 1 
2  | 1 
1  | 2 
3  | 2 
4  | 2 

這是上述示例的前兩個組合的映射。問題是,查找特定組合的查詢CombinationId似乎非常複雜。該表的兩個主要使用場景是遍歷所有組合,並檢索特定的組合。該表將被創建一次,永遠不會被更新。我通過JDBC使用SQLite。有沒有更簡單的方法或最佳實踐來實現這樣的映射?

+0

您的設計沒有任何問題。你應該澄清你的意思,「查找特定組合的CombinationId的查詢似乎非常複雜」。您想要查找組合ID的標準是什麼? – 2010-05-19 11:56:03

回答

2

的問題是,尋找一個特定組合的CombinationId查詢似乎是非常複雜的。

應該不會太壞。如果你想包含選定的項目(與允許的其他項目)的所有組合,它只是像:

SELECT combinationID 
FROM Combination 
WHERE objectId IN (1, 3, 4) 
GROUP BY combinationID 
HAVING COUNT(*) = 3 -- The number of items in the combination 

如果您只需要在特定的組合(不允許額外的項目),也可以是更象:

SELECT combinationID FROM (
    -- ... query from above goes here, this gives us all with those 3 
) AS candidates 

-- This bit gives us a row for each item in the candidates, including 
-- the items we know about but also any 'extras' 
INNER JOIN combination ON (candidates.combinationID = combination.combinationID) 

GROUP BY candidates.combinationID 
HAVING COUNT(*) = 3 -- Because we joined back on ALL, ones with extras will have > 3 

您也可以在這裏使用NOT EXISTS(或在原始查詢中),這似乎更容易解釋。

最後,您還可以看中,並有一個單一的,簡單的查詢

SELECT combinationID 
FROM Combination AS candidates 
INNER JOIN Combination AS allItems ON 
    (candidates.combinationID = allItems.combinationID) 
WHERE candidates.objectId IN (1, 3, 4) 
GROUP BY combinationID 
HAVING COUNT(*) = 9 -- The number of items in the combination, squared 

因此,換句話說,如果我們要找的{1,2},並有一個與{1,2組合,3},我們將有一個{候選人,allItems}的JOIN結果:COUNT(*)爲6行GROUP後ING,沒有4

{1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {2, 3} 

額外的3個結果,所以我們知道這不是我們」組合重新過後。

+0

謝謝你。我對SQL不太好,我的解決方案涉及嵌套查詢。這確實不是那麼糟糕。 – 2010-05-19 13:56:18

+0

+1非常感謝。你簡單而奇特的東西沒有奏效。第一個(「只有特定的組合(不允許額外的項目)」)完美運作 – IsmailS 2011-07-22 10:19:43

1

這可能是異端,但對於您的使用情景可能更好地工作,你自己存儲的組合爲某種複合(文本)值使用非規範化的結構:

CombinationId | Combination 
--------------------------- 
1    | |1|2| 
2    | |1|3|4| 

如果使規則是在生成複合值時總是對ObjectIds進行排序,因此很容易爲給定的一組對象檢索組合。

+1

好吧,可能將它分割成一個「組合」表,並有一個單獨列出行(1,1),(1,2)等的「combination_object」,以及每當插入某些內容時重新計算「組合」列的觸發器/從combination_object中刪除。 (基本上,這使得像基於功能的索引) – araqnid 2010-05-19 13:10:30