代码之家  ›  专栏  ›  技术社区  ›  Björn Pollex

如何将事物的组合映射到关系数据库?

  •  4
  • Björn Pollex  · 技术社区  · 14 年前

    我有一个表,它的记录表示某些对象。为了简单起见,我假设表只有一列,这是唯一的 ObjectId . 现在我需要一种方法来存储该表中的对象组合。组合必须是唯一的,但可以是任意长度。例如,如果我有 目标ID s

    1,2,3,4
    

    我要存储以下组合:

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

    Combinations 那是地图 目标ID s到 CombinationId s。所以每个组合都会收到一个唯一的Id:

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

    组合ID 一个特定组合的定义似乎非常复杂。此表的两个主要使用场景是迭代所有组合,以及检索特定组合。该表将创建一次,并且永远不会更新。我正在使用 SQLite 通过JDBC。有没有更简单的方法或最佳实践来实现这种映射?

    3 回复  |  直到 14 年前
        1
  •  3
  •   Cowan    14 年前

    应该不会太糟。如果希望所有组合都包含所选项目(允许附加项目),则如下所示:

    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
    

    您也可以在此处(或在原始查询中)使用notexists,这似乎更容易解释。

    最后,您还可以使用一个简单的查询

    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

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

    额外的3个结果是 COUNT(*) 六排之后 GROUP

        2
  •  1
  •   David Gelhar    14 年前

    这可能是异端邪说,但对于您的使用场景,最好使用非规范化结构,将组合本身存储为某种复合(文本)值:

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

    如果在生成复合值时总是对objectid进行排序,那么很容易检索给定对象集的组合。

        3
  •  0
  •   nvogel    14 年前

    另一种选择是使用关系值属性,在sqldbms中称为多集或嵌套表。

    http://download.oracle.com/docs/cd/B10500_01/appdev.920/a96594/adobjbas.htm#458790