Самый простой способ:
В момент изменения списка друзей - пересчитываем вручную друзей до 5ого уровня и сохраняем в таблице вида:
user_id,friend_id, level
Так как редактирование списка друзей - событие реже чем выборка" - то это имеет смысл чтобы выборка была быстрая.
Правда на больших объёмах - (Сотни людей) - могут быть проблемы :)
2ой способ, в момент выборки, так как у нас ограничен уровень вложения: (но сражу скажу что этот способ намного хуже)
друзья первого уровня:
select friend_id from users_friends where user_id =1;
Друзья второго уровня:
select lvl2.friend_id
from users_friends as lvl1
right join users_friends as lvl2 on lvl2.friend_id=lvl1.user_id
where lvl1.user_id =1;
Дальше уровни по аналогии
а чтобы это всё вместе возвращало:
select friend_id from users_friends where user_id =1 UNION
select lvl2.friend_id from users_friends as lvl1 right join users_friends as lvl2 on lvl2.friend_id=lvl1.user_id where lvl1.user_id =1;
Правда на больших объёмах производительнсть будет хромать.
использую такую таблицу:
users_friends: -друзья юзеров
user_id, friend_id (причём для каждой "дружбы" - две записи)
способ 3:
делать подобную выборку как в п1 и хранить в кеше локальном (требуется 5 запросов
Способ 4:
написать процедуру которая делает то же самое что в п1-п2