sql >> Databasteknik >  >> RDS >> Mysql

Grader av separation fråga

Så här utför du sökningen med hjälp av en sökning med bredd-först, kortaste väg, med JOIN. Det finns ingen magi i den här algoritmen, eftersom vi använder MySQL för att hitta vårt svar, och vi införlivar inte någon fancy sökalgoritm som använder någon form av heuristik eller optimering.

Min "vänner"-tabell har enkelriktade relationer, så vi har dubbletter i den meningen att både "1 till 2" och "2 till 1" lagras. Jag utesluter också is_active eftersom implementeringen kommer att vara uppenbar:

Här är uppgifterna:

member_id   friend_id
1           2
1           3
1           4
2           1
2           3
2           5
2           6
3           2
3           1
4           1
5           2
6           2
6           7
7           6
7           8
8           7

Vi har valt medlem 1, och vi frågar är 1 vän med 7, en vän till en vän, etc? Ett antal 0 betyder nej, och ett antal 1 betyder ja.

SELECT COUNT(*)
FROM friends f1
WHERE f1.member_id = 1
  AND f1.friend_id = 7

Om nej, är de då vän med en vän?

SELECT COUNT(*)
FROM friends f1
JOIN friends f2
  ON f2.member_id = f1.friend_id
WHERE f1.member_id = 1
  AND f2.friend_id = 7

Om nej, då vän till en vän till en vän?

SELECT COUNT(*)
FROM friends f1
JOIN friends f2
  ON f2.member_id = f1.friend_id
JOIN friends f3
  ON f3.member_id = f2.friend_id
WHERE f1.member_id = 1
  AND f3.friend_id = 7

Och så vidare...

Den tredje frågan skulle hitta sökvägen '1 till 2', '2 till 6' och '6 till 7', vilket returnerar antalet 1.

Varje fråga blir dyrare (på grund av det större antalet anslutningar), så du kanske vill begränsa sökningen någon gång. En cool sak är att den här sökningen fungerar från båda ändarna mot mitten, vilket är en enkel optimering som föreslås för sökningar på kortaste vägen.

Så här hittar du dessa gemensamma vänrekommendationer för medlem 1:

SELECT f2.friend_id
FROM friends f1
JOIN friends f2
  ON f2.member_id = f1.friend_id
LEFT JOIN friends f3
  ON f3.member_id = f1.member_id
  AND f3.friend_id = f2.friend_id
WHERE f1.member_id = 1
  AND f2.friend_id <> f1.member_id // Not ourself
  AND f3.friend_id IS NULL // Not already a friend


  1. MySQL ON DUPLICATE KEY infogas i en revisions- eller loggtabell

  2. Parallella transaktioner i mysql

  3. Slashes i MySQL-tabeller, men med PDO och parametriserade frågor. Vad händer?

  4. Kontrollera om användarnamnet redan finns i databasen MySQL PHP