递归数据建模和查询?

时间:2013-10-12 11:11:59

标签: sql recursion many-to-many relational-database data-modeling

我的数据模型中有一个对象如下:

// A word in the English language.
public class Word {
    private Long id;                 // Ex: 35
    private String text;             // Ex: "catlike"
    private Integer length;          // Ex: 7
    private String definition;       // Ex: "resembling a cat; stealthy"
    private List<Word> synonyms;     // Ex: "quick", "nimble"
    private List<Word> antonyms;     // Ex: "sluggish", "slow"

    // Getters, setters, ctors, etc. omitted for brevity; this is a simple POJO/bean
}

如您所见,它包含2个“递归”的其他单词列表(同义词和反义词)。 Word与其同义词及其反义词具有多对多关系。例如:“ cat-like ”的同义词可能是“ quick ”,但“ quick ”也是“的同义词>快速“等等。

我的计划是使用3个不同的表对数据库中的Word进行建模:1个主words表和2个人行横道/连接表:

  • words
  • synonyms(人行横道)
  • antonyms(人行横道)

表格及其字段:

[words]
    id            PRIMARY KEY AUTO INCREMENT
    text          VARCHAR
    length        INTEGER
    definition    VARCHAR

[synonyms]
    id            PRIMARY KEY AUTO INCREMENT
    word_1_id     FOREIGN KEY (words)
    word_2_id     FOREIGN KEY (words)

[antonyms]
    id            PRIMARY KEY AUTO INCREMENT
    word_1_id     FOREIGN KEY (words)
    word_2_id     FOREIGN KEY (words)

所以我的思考,如果我想查询其描述中包含“ metal ”的任何单词,或者有任何“ 金属“在其中,我的查询可能如下所示:

SELECT
    *
FROM
    words w
INNER JOIN
    synonyms s
ON
    w.id = s.word_1_id
WHERE
    w.definition LIKE '%metal%'
    OR
    ??? (synonym of w).definition LIKE '%metal%'

我是否正确地建立了这种重合关系?!?我觉得我要么死了,要么完全偏离基础,忽略了一些明显的东西。提前谢谢!

2 个答案:

答案 0 :(得分:0)

select * from (
SELECT
    *
FROM
    words w
WHERE
    w.definition LIKE '%metal%'
) UNION (
SELECT
    w1.*
FROM
    words w1,
    words w2,
    synonyms s
WHERE
    w1.id = s.word_1_id and
    w2.id = s.word_2_id and
    w2.definition LIKE '%metal%'
)

答案 1 :(得分:0)

  

我想要正确模式化我的Java POJO的表(每个Word可以有0 + Word同义词和反义词)

您的数据库模型很好,它应该能够在Java端支持您的模型。请注意,synonymsantonyms是方向性的,因此您应该为两个方向添加记录,或者在连接条件中将单个记录视为双向记录。

  

我可以查询其定义中包含“metal”的任何单词,以及它的任何同义词在其描述中也有“metal”。

您的查询不需要顶部的联接,可以使用EXISTS运算符完成,如下所示:

SELECT
    *
FROM words w
WHERE
    w.definition LIKE '%metal%'
    OR
    EXISTS (
        SELECT *
        FROM words ww
        JOIN synonyms ss ON ww.id = ss.word_1_id
        WHERE ww.definition LIKE '%metal%'
    )

请注意,此查询将为您提供符合条件的单词,而不是其同义词/反义词。应分别查询这些内容以完成Java表示所需的数据。为了完成查询的这一部分,您可能需要构建一个递归查询,通过一组多对多表为您提供与给定单词相关的所有单词。请查看this answer示例。

要对称地处理多对多表格,请更改

ww.id = ss.word_1_id

条件:

ww.id = ss.word_1_id OR ww.id = ss.word_2_id

这将模仿“W字具有同义词Q,或者是Q的同义词”的含义。