Oracle SQ通过同级标识同级

时间:2018-12-04 15:15:29

标签: sql oracle recursion hierarchy

我已将通过共享父项关联的记录组链接在一起。不幸的是,有一些相当复杂的家庭群体,而且很明显仅使用共享的父母关系是不够的-我也想考虑同胞关系。

要明确-这是实际的家庭群体,目前可以确定它们是否是共享的父母关系,但在某些情况下,一个孩子可能不会与仍通过兄弟姐妹联系在一起的另一个孩子共享父母。

enter image description here

因此,在以上示例中,Lou与Stacey没有共同的父母关系,但是Stacey是Nate的姐姐,而Nate是Deb的弟弟,而Deb是Lou的姐姐,后者将他们联系在一起。

为了论证,我们假设有一些这样的SQL:

SELECT A.ID, A.SIBS FROM A

哪个会生成这样的数据集:

ID  SIBS
A   B
A   C
B   A
C   A
C   D
D   C

我想从上述数据集中生成一个表,其中考虑了同级的同级-例如同级C与同级D和同级A相关,但与同级B通过同级A相关。结果表看起来像这样:

ID  SIBS
A   B
A   C
A   D
B   C
B   D
B   A
C   A
C   D
C   B
D   C
D   A
D   B

任何建议将不胜感激。

2 个答案:

答案 0 :(得分:2)

尚不清楚关系是否是自反的(即如果BA的“同级”,那么AB的“同级”)一些重复的行在您的数据中具有反向关系,而另一些行的属性不明显。

假设您的关系不是自反的,那么:

SQL Fiddle

Oracle 11g R2架构设置

CREATE TABLE A ( ID, SIBS ) AS
SELECT 'A', 'B' FROM DUAL UNION ALL
SELECT 'A', 'C' FROM DUAL UNION ALL
SELECT 'B', 'A' FROM DUAL UNION ALL
SELECT 'C', 'A' FROM DUAL UNION ALL
SELECT 'C', 'D' FROM DUAL UNION ALL
SELECT 'D', 'C' FROM DUAL UNION ALL
SELECT 'E', 'F' FROM DUAL UNION ALL
SELECT 'F', 'G' FROM DUAL UNION ALL
SELECT 'G', 'H' FROM DUAL;

查询1

SELECT DISTINCT
       CONNECT_BY_ROOT( ID ) AS ID,
       SIBS
FROM   A
WHERE  CONNECT_BY_ROOT( ID ) <> SIBS
CONNECT BY NOCYCLE
       PRIOR SIBS = ID
ORDER BY ID, SIBS

Results

| ID | SIBS |
|----|------|
|  A |    B |
|  A |    C |
|  A |    D |
|  B |    A |
|  B |    C |
|  B |    D |
|  C |    A |
|  C |    B |
|  C |    D |
|  D |    A |
|  D |    B |
|  D |    C |
|  E |    F |
|  E |    G |
|  E |    H |
|  F |    G |
|  F |    H |
|  G |    H |

查询2 :如果它们是自反的,则可以使用UNION [ALL]复制具有反向关系的表,然后使用以前的技术:

SELECT DISTINCT
       CONNECT_BY_ROOT( ID ) AS ID,
       SIBS
FROM   (
  SELECT ID, SIBS FROM A
  UNION
  SELECT SIBS, ID FROM A
)
WHERE  CONNECT_BY_ROOT( ID ) <> SIBS
CONNECT BY NOCYCLE
       PRIOR SIBS = ID
ORDER BY ID, SIBS

Results

| ID | SIBS |
|----|------|
|  A |    B |
|  A |    C |
|  A |    D |
|  B |    A |
|  B |    C |
|  B |    D |
|  C |    A |
|  C |    B |
|  C |    D |
|  D |    A |
|  D |    B |
|  D |    C |
|  E |    F |
|  E |    G |
|  E |    H |
|  F |    E |
|  F |    G |
|  F |    H |
|  G |    E |
|  G |    F |
|  G |    H |
|  H |    E |
|  H |    F |
|  H |    G |

答案 1 :(得分:1)

作为分层查询的替代方法,您还可以使用recursive subquery factoring

with r (pno, sibs) as (
  select a.id, a.sibs
  from a
  union all
  select r.pno, a.sibs
  from r
  join a on a.id = r.sibs
)
cycle pno, sibs set is_cycle to 1 default 0
select distinct pno, sibs
from r
where pno != sibs
order by pno, sibs;

PNO SIBS
--- ----
A   B   
A   C   
A   D   
B   A   
B   C   
B   D   
C   A   
C   B   
C   D   
D   A   
D   B   
D   C   

锚成员从您的表中获取原始数据。递归成员将到目前为止找到的每一行连接回到您的主表,并保留原始的pno(与connect_by_root(id)等效)。

我认为,分层查询的性能可能会更好,但这取决于您的数据,因此您可以尝试两种方法。