Неуклюжий SQL-запрос для «фида друзей» - PullRequest
1 голос
/ 24 августа 2009

Я пытаюсь закодировать элемент социальной сети на нашем сайте. У нас есть две таблицы: одна показывает пользователей, а другая показывает дружбу между этими пользователями.

Users:
 userid - PK, int
 name
 profilepic

Friendships:
 id - PK int
 userid
 friendid
 datecreated

Стол дружбы двусторонний - то есть кто-то может подружиться с кем-то, а он не дружит с ним обратно

Мне нужен запрос, который будет вызывать всех друзей для пользователя, новых друзей, которые были созданы его друзьями, а также имена и профили новых друзей.

Кошмар! Вся помощь очень ценится!

Ответы [ 5 ]

1 голос
/ 24 августа 2009

Правильно, у вас есть два разных запроса: один для информации о друге, а другой для информации о новом друге. Нет смысла пытаться делать их вместе.

все друзья для пользователя

SELECT friends.userid, friends.name, friends.profilepic
FROM friendships
JOIN users AS friends ON friends.userid=friendships.friendid
WHERE friendships.userid=[user's id]

новых друзей, которые установили их друзья

ОК, это отношения друг-друга, которые вы можете найти, дважды пройдя через таблицу дружбы. Это называется самостоятельным соединением:

SELECT friendoffriends.userid, friendoffriends.name, friendoffriends.profilepic
FROM friendships AS ships1
JOIN friendships AS ships2 ON ships2.userid=ships1.friendid
JOIN users AS friendoffriends ON friends.userid=ships2.friendid
WHERE ships1.userid=[user's id]
AND ships2.datecreated>=[last visit time]
1 голос
/ 24 августа 2009
-- all friends for a user
select f.*
from Users u
inner join Friendships f
on u.userid = f.userid
where u.userid = 1

-- new friends of friends
select ffu.*
from Users u
inner join Friendships f
on u.userid = f.userid
inner join Friendships ff
on f.friendid = ff.userid
inner join Users ffu
on ff.userid = ffu.userid
where u.userid = 1
and ff.datecreated > getdate() -30
0 голосов
/ 24 августа 2009

Это покажет новых друзей вашего друга, , какие новые друзья уже не ваши друзья :

SELECT DISTINCT fof.* 
FROM
(
  SELECT u.userid AS id, u.name, u.profilepic
  FROM users u
  JOIN friendships my_friends_friends
    ON my_friends_friends.friendid = u.userid
  JOIN friendships my_friends
    ON my_friends.friendid = my_friends_friends.userid
  WHERE
    my_friends.userid = 1
    AND
    my_friends_friends.datecreated > CURRENT_DATE - INTERVAL '10 DAY'
) fof
LEFT JOIN 
( 
  SELECT friendships.friendid 
  FROM friendships WHERE friendships.userid = 1
) f
  ON f.friendid = fof.id
WHERE
  f.friendid IS NULL
;

Предупреждение: использование этого запроса может привести к неприятностям с полицией DISTINCT. :)

0 голосов
/ 24 августа 2009

попробуйте это (сервер sql):

declare @users table (userid int primary key identity(1,1), name varchar(10), profilepic char(1))
declare @friendships table (id int primary key identity(1,1), userid int, friendid int, datecreated datetime)

insert into @users values ('bill','b')
insert into @users values ('matt','m')
insert into @users values ('steve','s')
insert into @users values ('fred','f')
insert into @users values ('joe','j')

insert into @friendships values (1,2,'8/24/2008')
insert into @friendships values (1,3,'8/24/2008')
insert into @friendships values (2,1,'8/24/2008')
insert into @friendships values (2,3,'8/24/2008')
insert into @friendships values (4,1,'8/24/2008')
insert into @friendships values (4,5,'8/24/2009')

--all firends
select
    u.*
    FROM @users u
        INNER JOIN (select
                        userid
                        FROM @Friendships
                        WHERE friendid=1
                    UNION
                    select
                        friendid
                        FROM @Friendships
                        WHERE userid=1
                   ) dt ON u.userid=dt.userid



--new firends of friends
select
    u.*
    FROM (select
              userid
              FROM @Friendships
              WHERE friendid=1
          UNION
          select
              friendid
              FROM @Friendships
              WHERE userid=1
         ) dt
        INNER JOIN @friendships f ON dt.userid=f.userID
        INNER JOIN @users u ON f.friendid=u.userid
    WHERE f.datecreated>=GETDATE()-14 --2 weeks

OUTPUT

userid      name       profilepic
----------- ---------- ----------
2           matt       m
3           steve      s
4           fred       f

(3 row(s) affected)

userid      name       profilepic
----------- ---------- ----------
5           joe        j

(1 row(s) affected)
0 голосов
/ 24 августа 2009

Это не то, что должно быть сделано в чистом SQL. Хотя ваши отношения могут быть тривиально определены сейчас, вы можете (захотите?) Добавить что-то в список элементов в «ленте». Это то, что гораздо лучше подходит для агрегирования в потребляющем коде.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...