【发布时间】:2013-01-29 22:49:41
【问题描述】:
我在工作中遇到了一个查询,但无法弄清楚它是如何工作的。查询的作用是查找今天是其父级的人的所有父级。
这里的诀窍是每个父子关系都有一个有效的持续时间。
以此数据集作为参考:
从 01-01-2012 到 02-02-2015,GrandParent 是父亲的父母
从 01-01-2012 到 02-02-2011,父亲是孩子的父母
孩子只是最底层的人
NewFather 是 Child 从 01-01-2012 到 02-02-2014 的父母
现在对 Child 有效的父母列表应仅包含 NewFather
为了获取列表,之前我们使用了这个 SQL:
SELECT connect_by_root per_id2 AS per_id2,
per_id1,
LEVEL AS per_level,
n.entity_name
FROM ci_per_per pp,
ci_per_name N
WHERE N.per_id = per_id1
AND start_dt <= SYSDATE
AND ( end_dt IS NULL
OR end_dt >= SYSDATE )
START WITH per_id2 = :personID
CONNECT BY NOCYCLE PRIOR per_id1 = per_id2;
personID 是一个绑定变量
此查询不起作用,因为 where 子句的行为是它首先获取所有记录,然后检查非连接条件(检查开始日期和结束日期)。这导致它给出的父母名单为NewFather, GrandParent,这是完全错误的!
因此,查询更改为以下内容:
SELECT connect_by_root per_id2 AS per_id2,
per_id1,
LEVEL AS per_level,
n.entity_name
FROM ci_per_per pp,
ci_per_name N
WHERE N.per_id = per_id1
AND start_dt <= SYSDATE
AND ( end_dt IS NULL
OR end_dt >= SYSDATE )
START WITH per_id2 = (SELECT per_id
FROM ci_acct_per
WHERE per_id = :personID
AND pp.start_dt <= SYSDATE
AND ( pp.end_dt IS NULL
OR pp.end_dt >= SYSDATE ))
CONNECT BY NOCYCLE PRIOR per_id1 = per_id2;
现在我不明白的是:
start with 子句中的 where 条件如何以这种方式影响查询的行为?
我不喜欢这个查询的另一件事是,它使用了一个名为 ci_acct_per 的完全不相关的表,其中只是为 ci_per_per 中的每个人提供了一个 per_id 列。
我们可以做得更好吗?是否有更简洁的方法可用于修复原始查询?
更新
此查询仅在层次结构中较高时有效,而在我们正在寻找孩子时无效。但是,此查询从不寻找孩子,也不应该这样做。
【问题讨论】:
标签: database oracle hierarchy connect-by