递归查询加入结果集与table只要有更多的匹配

Recursive query to join the result set with the table as long as there are more matches

CUSTOMER
customer_id | email1 | email2 | phone1 | phone2

REGISTRATION
registration_id | email3 | ip

REGISTRATION_TO_CUSTOMER
registration_id | customer_id | email4

BANNED
banned_id   | ip | email | phone

数据样本:

CUSTOMER 
1 | test1_1@mail.com  | test1_2@mail.com | 1 | 11|
2 | test2_1@mail.com  | test2_2@mail.com | 2 | 1 |
3 | test3_1@mail.com  | test3_2@mail.com | 3 | 33|

REGISTRATION
1 | test1_1a@mail.com | 192.168.1.1
2 | test2_1a@mail.com | 192.168.1.3
3 | test3_1a@mail.com | 192.168.1.3

REGISTRATION_TO_CUSTOMER
1 | 1 | test1_1a@mail.com 
2 | 2 | test2_1b@mail.com 
3 | 3 | test3_1c@mail.com 

BANNED
1 | 192.168.1.3 | null           | null
3 | null        | test2@mail.com | null

解释:

所以我尝试了这个(但 return 没有任何结果):

    SELECT DISTINCT customer_id,
    email1,
    email2,
    email3,
    email4,
    phone1,
    phone2,
    ip
FROM (
    SELECT *
    FROM (
        SELECT r.ip,
            r.registration_id,
            r.email3,
            rc.email4,
            c.customer_id,
            c.email1,
            c.email2,
            c.phone1,
            c.phone2
        FROM (
            SELECT registration_id,
                email3,
                ip
            FROM REGISTRATION
            ) r
        INNER JOIN (
            SELECT registration_id,
                customer_id,
                email4
            FROM REGISTRATION_TO_CUSTOMER
            ) rc
            ON r.registration_id = rc.registration_id
        INNER JOIN (
            SELECT customer_id,
                email1,
                email2,
                phone1,
                phone2
            FROM CUSTOMER
            ) c
            ON rc.customer_id = c.customer_id
        ) start WITH (
            email1,
            email2,
            email3,
            email4,
            phone1,
            phone2,
            ip
            ) IN (
            SELECT DISTINCT CUST.email1,
                CUST.email2,
                CUST.email3,
                CUST.email4,
                CUST.phone1,
                CUST.phone2,
                CUST.ip
            FROM (
                SELECT r.ip,
                    r.registration_id,
                    r.email3,
                    rc.email4,
                    c.customer_id,
                    c.email1,
                    c.email2,
                    c.phone1,
                    c.phone2
                FROM (
                    SELECT registration_id,
                        email3,
                        ip
                    FROM REGISTRATION
                    ) r
                INNER JOIN (
                    SELECT registration_id,
                        customer_id,
                        email4
                    FROM REGISTRATION_TO_CUSTOMER
                    ) rc
                    ON r.registration_id = rc.registration_id
                INNER JOIN (
                    SELECT customer_id,
                        email1,
                        email2,
                        phone1,
                        phone2
                    FROM CUSTOMER
                    ) c
                    ON rc.customer_id = c.customer_id
                ) CUST
            INNER JOIN BANNED
                ON CUST.ip = BANNED.ip
                    OR CUST.email1 = BANNED.email
                    OR CUST.email2 = BANNED.email
                    OR CUST.email3 = BANNED.email
                    OR CUST.email4 = BANNED.email
                    OR CUST.phone1 = BANNED.phone
                    OR CUST.phone2 = BANNED.phone
            ) connect BY nocycle email1 = prior email1
        OR email2 = prior email2
        OR email3 = prior email3
        OR email4 = prior email4
        OR phone1 = prior phone1
        OR phone2 = prior phone2
        OR ip = prior ip
    )
ORDER BY customer_id

这个查询看起来很有希望:

select distinct id, ip, email, phone
  from (
    select id, ip, email, phone, 
      from customer start with 
        (ip, email, phone) in (
          select distinct c.ip, c.email, c.phone
            from customer c join banned b 
              on b.ip = c.ip or b.email = c.email or b.phone = c.phone)
      connect by nocycle ip = prior ip or email = prior email or phone = prior phone)
  order by id

这里是fiddle


编辑:修改后的查询考虑了新表,在问题中添加:registration, registration_to_customer 以及其他电话和电子邮件。

with cust as (
  select customer_id cid, registration_id rid, ip, phone1, phone2, 
      email1, email2, email3, email4
    from registration r
      join registration_to_customer rc using (registration_id)
      join customer using (customer_id))
select distinct cid, rid, ip, phone1, phone2, email1, email2, email3, email4
  from cust
  start with (ip, phone1, phone2, email1, email2, email3, email4)
    in (
      select b.ip, phone1, phone2, email1, email2, email3, email4 from cust
        join banned b on b.ip = cust.ip
          or b.email in (cust.email1, cust.email2, cust.email3, cust.email4)
          or b.phone in (cust.phone1, cust.phone2))
  connect by nocycle 
    email1 in (prior email1, prior email2, prior email3, prior email4) or
    email2 in (prior email1, prior email2, prior email3, prior email4) or
    email3 in (prior email1, prior email2, prior email3, prior email4) or
    email4 in (prior email1, prior email2, prior email3, prior email4) or
    phone1 in (prior phone1, prior phone2) or
    phone2 in (prior phone1, prior phone2) or
    ip = prior ip
  order by cid