sql >> Base de Datos >  >> RDS >> Oracle

Marcar personas que comparten características comunes con Oracle SQL

Aquí hay una forma de hacer esto, usando una consulta jerárquica ("conectar por"). El primer paso es extraer las relaciones iniciales de los datos base; la consulta jerárquica se basa en el resultado de este primer paso. Agregué una fila más a las entradas para ilustrar un nodo que es un componente conectado por sí mismo.

Marcó los componentes conectados como A y B; por supuesto, eso no funcionará si tiene, digamos, 30,000 componentes conectados. En mi solución, uso el nombre de nodo mínimo como marcador para cada componente conectado.

with
  sample_data (id, feature) as (
    select 1,  1 from dual union all
    select 1,  2 from dual union all
    select 1,  3 from dual union all
    select 2,  3 from dual union all
    select 2,  4 from dual union all
    select 2,  6 from dual union all
    select 3,  5 from dual union all
    select 3, 10 from dual union all
    select 3, 12 from dual union all
    select 4, 12 from dual union all
    select 4, 18 from dual union all
    select 5, 10 from dual union all
    select 5, 30 from dual union all
    select 6, 40 from dual
  )
-- select * from sample_data; /*
, initial_rel(id_base, id_linked) as (
    select distinct s1.id, s2.id
      from sample_data s1 join sample_data s2
                          on s1.feature = s2.feature and s1.id <= s2.id
  )
-- select * from initial_rel; /*
select     id_linked as id, min(connect_by_root(id_base)) as id_group
from       initial_rel
start with id_base <= id_linked
connect by nocycle prior id_linked = id_base and id_base < id_linked
group by   id_linked
order by   id_group, id
;

Salida:

     ID   ID_GROUP
------- ----------
      1          1
      2          1
      3          3
      4          3
      5          3
      6          6

Luego, si necesita agregar ID_GROUP como una BANDERA a los datos base, puede hacerlo con una unión trivial.