Oracle SQ Определить братьев и сестер через братьев и сестер - PullRequest
0 голосов
/ 04 декабря 2018

Я связал вместе группы записей, которые связаны через общего родителя.К сожалению, есть несколько довольно сложных семейных групп, и стало ясно, что просто использовать общие родительские отношения недостаточно - я также хочу принять во внимание родственные отношения.

Для ясности - это фактические семейные группы, которые в настоящее время идентифицируются, если они являются общими отношениями между матерью или отцом, но в некоторых случаях ребенок не может делить родителей с другим ребенком, который все еще связан с ними черезродной брат

enter image description here

Итак, в приведенном выше примере Лу не имеет общих родительских отношений со Стейси, но Стейси - сестра Нейта, брата Деб, которыйэто сестра Лу, которая связывает их вместе.

В качестве аргумента, скажем, у нас есть некоторый 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 голосов
/ 04 декабря 2018

В качестве альтернативы иерархическому запросу вы также можете использовать рекурсивный факторинг подзапросов :

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)).

Я думаю, что иерархический запрос, вероятно, будет работать лучше, ноэто немного зависит от ваших данных, поэтому вы можете попробовать оба подхода.

0 голосов
/ 04 декабря 2018

Непонятно, являются ли отношения рефлексивными (т. Е. Если B является "родным братом" A, тогда A является "родным братом" B), поскольку у вас есть несколько повторяющихся строк с обращенными отношениями вваши данные и некоторые, где это свойство не очевидно.

Если предположить, что ваши отношения не являются рефлексивными, то:

SQL Fiddle

Oracle11g Настройка схемы 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

Результаты :

| 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

Результаты :

| 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 |
...