1

下面的查询大约需要一分钟。我相信性能不佳是由两个“IN(SELECT ...”子句引起的。我有一个术语表,其中一个可以通过 term_relationship 表连接到另一个。这些关系可以是递归的,例如 dog 是一种哺乳动物,哺乳动物是一种动物。这种递归可以是任何深度,但可能不超过 10 个级别。我正在尝试选择所有与 A 型具有(潜在递归)关系并具有(潜在递归)关系的术语使用 B 类型。我认为用对外部查询的限制替换两个“IN (SELECT ...”子句会提高性能,但无法弄清楚如何使用 CONNECT BY 子句来做到这一点。有人可以帮忙吗?

SELECT term_name
FROM term
WHERE term_id IN 
   (SELECT term_id 
    FROM term_relationship 
    START WITH related_term_id = 123
    CONNECT BY NOCYCLE PRIOR term_id = related_term_id)
AND term_id IN 
   (SELECT term_id 
    FROM term_relationship 
    START WITH related_term_id = 456
    CONNECT BY NOCYCLE PRIOR term_id = related_term_id)
4

1 回答 1

2

与其只使用不同的起始值执行两次相同的CONNECT BY查询,不如通过将两个起始值都提供给子查询的一个实例来执行一次。此更改将为您提供term_id与您的任一起始值相关的所有 s,但是,您只需要term_id与您的两个起始值相关的那些 s。为此,您需要按 term_id 对结果进行分组,并限制为计数超过 1 的结果:

SELECT term_name
  FROM term
 WHERE term_id IN 
    (SELECT term_id 
       FROM term_relationship 
      START WITH related_term_id in (123, 456)
    CONNECT BY NOCYCLE PRIOR term_id = related_term_id
      group by term_id having count(*) >= 2)

编辑
使用上面的代码,我对您的数据做出了一个可能不正确的假设。我假设一个树状结构,您从分支上的节点开始,然后像图 A​​ 中那样向根部移动,但是,如果您的数据看起来像图 B,那么如果您从节点 7 和 9 开始,上述查询将失败由于节点 7 有两条路径返回节点 1,上述查询将返回节点 1 两次,从而将其误识别为公共节点。

A)   -(1)-                    B)   -(1)-
    /  |  \     (8)               /  |  \     (8)
  (2)  |  (3)    |              (2)  |  (3)    |
   |  (4)  |    (9)              |  (4)  |    (9)
  (5)     (6)                   (5)     (6)
           |                      \     /
          (7)                      -(7)-

下面的查询对此进行了更正,并将正确识别起始节点 7 和 9 没有节点是公共的,但是,对于起始节点 7 和 4,节点 1 被标识为公共节点:

SELECT term_name
  FROM term
 WHERE term_id IN 
    (SELECT term_id 
     FROM term_relationship 
    START WITH related_term_id in (123, 456)
  CONNECT BY NOCYCLE PRIOR term_id = related_term_id
    group by term_id
   having count(distinct connect_by_root related_term_id) >= 2)
于 2019-02-08T18:50:27.593 回答