我有一个表,其记录表示某些对象。为了简单起见,我将假定该表只有一列,这是唯一的ObjectId。现在,我需要一种方法来存储该表中对象的组合。组合必须是唯一的,但可以是任意长度。例如,如果我有ObjectIds
ObjectId
1,2,3,4
我想存储以下组合:
{1,2}, {1,3,4}, {2,4}, {1,2,3,4}
不需要订购。我当前的实现是要有一个Combinations将ObjectIds映射到CombinationIds的表。因此,每个组合都会收到一个唯一的ID:
Combinations
CombinationId
ObjectId | CombinationId ------------------------ 1 | 1 2 | 1 1 | 2 3 | 2 4 | 2
这是上面示例的前两个组合的映射。问题在于,查找CombinationId特定组合的的查询似乎非常复杂。该表的两个主要使用方案是遍历所有组合,并检索特定的组合。该表将创建一次,并且永远不会更新。我正在通过JDBC使用SQLite。有没有更简单的方法或最佳实践来实现这种映射?
问题在于,用于查找特定组合的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 NOTISTS,这似乎更容易解释。
最后,您也可以看中一个简单的查询
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}结合在一起,我们将得到一个{candidates,allItems}JOIN结果:
JOIN
{1, 1}, {1, 2}, {1, 3}, {2, 1}, {2, 2}, {2, 3}
额外的3个结果导致ingCOUNT(*)后为6行GROUP,而不是4行,因此我们知道这不是我们要遵循的组合。
COUNT(*)
GROUP