没有父/子关系的递归实体

时间:2013-02-14 00:18:18

标签: sql recursion recursive-query

我试图在RDBMS中表示以下递归关系:

enter image description here

作为一个基本示例,我们有以下字段:

1 - computer science
2 - computer engineering
3 - electrical engineering
4 - mathematics

我希望将相似的领域相互联系起来。我可以使用第二个表将字段相互关联。最理想的是,我可以想象它看起来像这样:

+----------+----------+
| field1   | field2   |
+----------+----------+
|    4     |    1     | (math -> comp sci)
|    4     |    2     | (math -> comp eng)
|    4     |    3     | (math -> elect eng)
|    2     |    1     | (comp eng -> comp sci)
|    2     |    3     | (comp eng -> elect eng)
+----------+----------+

但是,如果密钥是(field1,field2),我可以看到两个潜在的问题:

  1. 元组可以重复,尽管是无序的
  2. 如果对哪个字段在哪个列中没有重要性(如 sgeddes 指出,查询两列并过滤掉重复项),可能会使查询不必要地复杂化。
  3. 例如:

    +----------+----------+
    | field1   | field2   |
    +----------+----------+
    |    1     |    4     | (comp sci -> math)
    |    4     |    3     | (math -> elect eng)
    |    4     |    2     | (math -> comp eng)
    |    3     |    4     | (elect eng -> math)
    |    2     |    1     | (comp eng -> comp sci)
    |    3     |    2     | (elect eng -> comp eng)
    |    1     |    2     | (comp sci -> comp eng)
    +----------+----------+
    

    我应该如何处理非分层递归关系?

    我应该继续并故意复制每个元组,就像在第二个表中一样?还是有另外一种我过度看待的方法吗?

2 个答案:

答案 0 :(得分:1)

我已经多次看过这种方法了。从来没有成为一个忠实的粉丝,因为我不得不查询两个字段的匹配并过滤掉重复的结果。那两个以上相似的字段呢?可能会变得相当混乱。

使用上面的示例,另一种方法是引入一个SimilarField表。它将存储SimilarId和FieldId(有些人会争论第三个Identity字段,SimilarFieldId)。因此,如果英语和文学是相似的领域,那么你可以:

SimilarId   FieldId
1           1         (English)
1           2         (Literature)

此方法允许您在字段及其相似字段之间建立1-n关系。

<强> - 编辑 -

在回复您的评论时,不确定您的示例如何不起作用:

SimilarId   FieldId
1           1         (English)
1           2         (Literature)
1           3         (Reading)
2           2         (Literature)
2           4         (History)
3           4         (History)
3           5         (Art History)

您可以根据需要创建尽可能多的相似字段。

要获取与文献相关联的所有字段,您的查询可能如下所示:

SELECT DISTINCT F.FieldId, F.FieldName
FROM Field F JOIN 
      SimilarField S ON F.FieldId = S.FieldId
WHERE S.SimilarId IN (
      SELECT SimilarId 
      FROM SimilarField
      WHERE FieldId = 2 
   )

这是一个示例SQL Fiddle

答案 1 :(得分:1)

重复问题的一种常见方法是确保field1始终包含元组中的最低ID,并在两列上都包含UNIQUE键。那么SELECT的条件就可以是WHERE field1 = @id OR field2 = @id