sqlsql-server-2008contactscontact-list

SQL Server: how to select First, Second and Third degree contacts


I'm working on a social web-site project and I need to list "First, Second and Third Degree Contacts" of my contacts. I'm using SQL Server AND C#

Assume a contact table like this:

enter image description here

For first degree contact:

Query I use to select this:

SELECT contact_2 FROM Contacts_Table WHERE contact_1 like 'gulsah'

For second degree contact:

If gulsah is me again then my second degree contacts are: mali

What makes it difficult is to select contacts of my contacts who are not my first degree contact.

I can select mutual contacts but I guess it is not the right approach.

For example, to select mutual contacts of me (gulsah) and burak:

SELECT contact_1 FROM (SELECT * FROM Contact_Test 
  WHERE contact_2 like 'burak') a
     INNER JOIN (SELECT contact_1 FROM Contact_Test 
     WHERE (contact_2 = 'gulsah')) b 
ON a.contact_1 = b.contact_1

This query works but as I said, it's not the right approach for this job.

For third degree contact:

If gulsah is me again then my third degree contacts are_ mehmet,ahmet

I need to select contacts of my contacts' contacts who are not my first and second degree contact :)

Here is a post from Linkedin which explains contact level.

Thanks for responses.


Solution

  • Here's my approach:

    1. Add my contact to a special collected contact list.

    2. For every contact in the collected list as Contact_1 of the contact table, add its corresponding Contact_2 unless that contact is already in the collected list.

    3. Repeat step #2 the number of times that is the target degree number minus one.

    4. Repeat the query in step #2 once more, but this time simply return the result set (do not add the rows to the collected list).

    The script:

    DECLARE @MyContact varchar(50), @DegreeNumber int;
    SET @MyContact = 'gulsah';
    SET @DegreeNumber = 3;
    
    DECLARE @CollectedContacts TABLE (Contact varchar(50));
    INSERT INTO @CollectedContacts (Contact) VALUES (@MyContact);
    
    WHILE @DegreeNumber > 1 BEGIN
      INSERT INTO @CollectedContacts (Contact)
      SELECT ct.Contact_2
      FROM Contacts_Table ct
        INNER JOIN @CollectedContacts cc ON ct.Contact_1 = cc.Contact
        LEFT JOIN @CollectedContacts cc2 ON ct.Contact_2 = cc2.Contact
      WHERE cc2.Contact IS NULL;
    
      SET @DegreeNumber = @DegreeNumber - 1;
    END;
    
    SELECT ct.Contact_2
    FROM Contacts_Table ct
      INNER JOIN @CollectedContacts cc ON ct.Contact_1 = cc.Contact
      LEFT JOIN @CollectedContacts cc2 ON ct.Contact_2 = cc2.Contact
    WHERE cc2.Contact IS NULL;
    

    As you can see, both the degree number and 'my' contact are parametrisable. I'm using the varchar type for contacts, but that of course can easily be replaced with int, if needed.