Andrew
Andrew

Reputation: 7788

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

DATA SAMPLE:

CUSTOMER 
1 | [email protected]  | [email protected] | 1 | 11|
2 | [email protected]  | [email protected] | 2 | 1 |
3 | [email protected]  | [email protected] | 3 | 33|

REGISTRATION
1 | [email protected] | 192.168.1.1
2 | [email protected] | 192.168.1.3
3 | [email protected] | 192.168.1.3

REGISTRATION_TO_CUSTOMER
1 | 1 | [email protected] 
2 | 2 | [email protected] 
3 | 3 | [email protected] 

BANNED
1 | 192.168.1.3 | null           | null
3 | null        | [email protected] | null

Explanation:

So I tried this (and it returns no results whatsoever):

    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

Upvotes: 0

Views: 96

Answers (1)

Ponder Stibbons
Ponder Stibbons

Reputation: 14858

This query looks promising:

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

Here is fiddle.


Edit: The modified query taking into account new tables, added in question: registration, registration_to_customer and additional phones and emails.

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

Upvotes: 2

Related Questions