Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SQL query 6 degrees of separation for network analysis

Tags:

sql

postgresql

I'm building a network analysis using D3.js to show connected phone numbers within my app down to six degrees of separation. The SQL (postgres) to find initial connections is below and fairly straightforward. However, I am stumped on how to modify this to traverse through six levels of connections then stop.

SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN (SELECT hash FROM game.phone_hashes WHERE player_id = $1);

I have found mentions of Common Table Expressions (CTE) and recursion through research into this problem, but am unsure how to apply them here.

What I'm aiming for is to get all the players connected to the initial player ($1) through a common phone hash, then all the players connected to each of those connections through a common phone hash, and on and on out to 6 degrees of separation.

like image 651
MattDionis Avatar asked Nov 19 '15 21:11

MattDionis


People also ask

How would you solve a six degrees of separation problem?

The fastest O(n) algorithm for six-degrees of separation would probably be finding the sets of all users 1-step away from UserX and UserY, and finding the intersection of those two sets. If none, then add the users 2-steps from UserX and intersect; then add users 2-steps from UserY and intersect; etc. up to 3.

What are the six degrees of separation?

Six degrees of separation is the theory that any person on the planet can be connected to any other person on the planet through a chain of acquaintances that has no more than five intermediaries.

How SQL query is executed internally?

SQL Query mainly works in three phases . 1) Row filtering - Phase 1: Row filtering - phase 1 are done by FROM, WHERE , GROUP BY , HAVING clause. 2) Column filtering: Columns are filtered by SELECT clause. 3) Row filtering - Phase 2: Row filtering - phase 2 are done by DISTINCT , ORDER BY , LIMIT clause.

Is 6 Degrees of Separation true?

The huge volumes of data collected by the game allowed sociology researchers to analyse exactly how interconnected Hollywood actors really are, and they found that six degrees of separation does indeed appear to exist, but it's people's random acquaintances, not their friends, that are the key to all of this.


2 Answers

I think this is what you meant:

with recursive tc as(
select $1 as player_id, 1 as level
  union
select ph2.player_id, level+1
  from tc, phone_hashes ph1, phone_hashes ph2
  where tc.player_id=ph1.player_id
  and ph1.hash=ph2.hash
  and tc.level < 6  
)    
select distinct player_id from tc
like image 163
maniek Avatar answered Sep 17 '22 13:09

maniek


Think it would be:

-- 6 degrees of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes
 WHERE hash IN
 (SELECT hash FROM game.phone_hashes
  WHERE hash IN
  (SELECT hash FROM game.phone_hashes
   WHERE hash IN
   (SELECT hash FROM game.phone_hashes
    WHERE hash IN 
    (SELECT hash FROM game.phone_hashes
     WHERE hash IN
     (SELECT hash FROM game.phone_hashes
      WHERE player_id = $1))))));

Please see workings below:

-- 1 degree of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes WHERE player_id = $1);

-- 2 degrees of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes 
 WHERE hash IN
 (SELECT hash FROM game.phone_hashes
  WHERE player_id = $1));

-- 3 degrees of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes
 WHERE hash IN
 (SELECT hash FROM game.phone_hashes
  WHERE hash IN
  (SELECT hash FROM game.phone_hashes
   WHERE player_id = $1)));

-- 4 degrees of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes
 WHERE hash IN
 (SELECT hash FROM game.phone_hashes
  WHERE hash IN
  (SELECT hash FROM game.phone_hashes
   WHERE hash IN
   (SELECT hash FROM game.phone_hashes
    WHERE player_id = $1))));


-- 5 degrees of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes
 WHERE hash IN
 (SELECT hash FROM game.phone_hashes
  WHERE hash IN
  (SELECT hash FROM game.phone_hashes
   WHERE hash IN
   (SELECT hash FROM game.phone_hashes
    WHERE hash IN
    (SELECT hash FROM game.phone_hashes
     WHERE player_id = $1)))));

-- 6 degrees of separation
SELECT player_id, ps.player_state, ps.email, ph.create_date
FROM game.phone_hashes ph
INNER JOIN game.customer_settings cs ON cs.id = ph.player_id
WHERE hash IN
(SELECT hash FROM game.phone_hashes
 WHERE hash IN
 (SELECT hash FROM game.phone_hashes
  WHERE hash IN
  (SELECT hash FROM game.phone_hashes
   WHERE hash IN
   (SELECT hash FROM game.phone_hashes
    WHERE hash IN 
    (SELECT hash FROM game.phone_hashes
     WHERE hash IN
     (SELECT hash FROM game.phone_hashes
      WHERE player_id = $1))))));
like image 30
Steve Chambers Avatar answered Sep 17 '22 13:09

Steve Chambers