【问题标题】:How to map combinations of things to a relational database?如何将事物组合映射到关系数据库?
【发布时间】:2011-02-21 08:02:27
【问题描述】:

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

1,2,3,4

我要存储以下组合:

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

订购不是必需的。我目前的实现是有一个表CombinationsObjectIds 映射到CombinationIds。所以每个组合都会收到一个唯一的 ID:

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

这是上面示例的前两种组合的映射。问题是,查找特定组合的CombinationId 的查询似乎非常复杂。该表的两个主要使用场景是遍历所有组合,并检索特定组合。该表将被创建一次并且永远不会被更新。我通过 JDBC 使用SQLite。有没有更简单的方法或最佳实践来实现这样的映射?

【问题讨论】:

  • 您的设计没有问题。您可能应该澄清“用于查找特定组合的 CombinationId 的查询似乎非常复杂”的意思。您要查找组合 ID 的标准是什么?

标签: sql orm combinations


【解决方案1】:

问题是,查找特定组合的 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} 的组合,我们将有一个 {candidates, allItems} JOIN 结果:

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

额外的 3 导致 COUNT(*)GROUPing 之后是 6 行,而不是 4,所以我们知道这不是我们想要的组合。

【讨论】:

  • 谢谢。我对 SQL 不是很好,我的解决方案涉及嵌套查询。这确实还不错。
  • +1 非常感谢。你的简单而花哨的东西没有奏效。第一个 (only the specific combination (no extra items allowed)) 完美运行
【解决方案2】:

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

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

如果您制定规则,在生成复合值时始终对 ObjectId 进行排序,则很容易检索给定对象集的组合。

【讨论】:

  • 好吧,可能将其拆分为“组合”表,并有一个“组合对象”分别列出行 (1,1)、(1,2) 等,以及一个重新计算“组合”的触发器" 每当有东西被插入到组合对象中/从组合对象中删除时,列。 (本质上这是在制作基于函数的索引)
【解决方案3】:

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

如果对象集除了集合本身之外没有标识符,则关系值属性可能是有意义的。但是,我认为任何 SQL DBMS 都不允许在该类型的列上声明键,因此如果您没有可以使用的替代键,这可能会成为问题。

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

【讨论】:

    猜你喜欢
    • 2014-05-02
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-11-05
    • 1970-01-01
    • 2021-02-07
    • 2016-06-12
    相关资源
    最近更新 更多