0

我创建了一个“推荐好友”的 php 脚本,类似于 facebook。我的数据库有 2 个表,users(user_id, name, surname, profile)friends(friends_id, user_one, user_two)。我的代码如下:

<?php

//----- gets all friends of my friends -------

$friends_of_friends = mysql_query(" SELECT u.*
        FROM (SELECT DISTINCT user_one as user_id
            FROM friends
            WHERE user_two IN (SELECT user_one as user_id
                         FROM friends
                     WHERE user_two = '$session_user_id'
                     UNION DISTINCT
                     SELECT user_two
                     FROM friends
                     WHERE user_one = '$session_user_id'
                       )
            UNION DISTINCT
            SELECT DISTINCT user_two
            FROM friends
            WHERE user_one IN (SELECT user_one as user_id
                     FROM friends
                     WHERE user_two = '$session_user_id'
                     UNION DISTINCT
                     SELECT user_two
                         FROM friends
                     WHERE user_one = '$session_user_id'
                       )
           ) f
          JOIN users u
          ON u.user_id = f.user_id  ");

while ($run_friends= mysql_fetch_assoc($friends_of_friends)) {
    $friend_friend_id = $run_friends['user_id'];


 // ---- gets friends of my friends that are not my friends -------------------------------

 $check_friend_query = mysql_query("  SELECT friends_id from friends WHERE  (user_one='$session_user_id' AND user_two='$friend_friend_id') OR (user_one='$friend_friend_id' AND user_two='$session_user_id')   ");

   if (mysql_num_rows($check_friend_query) != 1){ 

    $not_friends = mysql_query("SELECT `user_id`, `name`, `surname`, `email`, `profile` FROM `users` WHERE (`user_id`='$friend_friend_id' AND `user_id`!='$session_user_id')  ");

       while ($run_not_friends= mysql_fetch_assoc($not_friends)) {
         $not_friend_id = $run_not_friends['user_id'];
                 echo $not_friend_id;
       } //end while

   } //end if

} //end while

?>

我的代码运行良好,并为我提供了我想要的所有朋友的朋友。是否可以将上述所有代码组合在一个 spl 语句中?知道怎么做吗?

4

1 回答 1

1

对于您要实现的目标,您的查询似乎非常复杂。据我所知,与您的原始查询相关的唯一字段是user_oneand user_twoinfriendsuser_idin users。通过使用子查询,查询的运行时间将成倍增加。

这意味着您可以将其重写为以下查询,这应该会快得多,因为 mysql 可以缩短很多结果,而不必执行每个子查询。它返回来自某个用户的朋友的所有用户,我将从这里调用“x”。不是朋友的朋友的“x”的朋友不会返回,并且由于最后的 AND,它也不会返回用户本身。

SELECT DISTINCT c.* FROM friends as a, friends as b, users as c
WHERE (a.user_one = 1 AND (
  (a.user_two = b.user_one AND b.user_two = c.user_id) OR
  (a.user_two = b.user_two AND b.user_one = c.user_id)
  ) OR (a.user_two = 1 AND (
  (a.user_one = b.user_one AND b.user_two = c.user_id) OR
  (a.user_one = b.user_two AND b.user_one = c.user_id)
  )
 )) AND c.user_id != 1
ORDER BY c.`user_id` ASC

要从结果中删除所有与“x”直接好友的用户,您可以使用NOT IN( ... ). 我为此使用了子查询,因为我不相信没有子查询就可以做到这一点。我本可以加入一个额外的friends表,但即使我测试当前用户是否是来自c.user_id该新加入表的朋友,查询也可以通过匹配该部分查询中的任何其他朋友来进行,这是我们不做的不想。子查询将(或应该)在每个唯一的朋友之间只执行一次。我认为如果您将这些查询分开并将两个返回的数组相互比较,性能会更好,但这不允许您LIMIT在查询中使用。

SELECT DISTINCT c.* FROM friends as a, friends as b, users as c
WHERE (a.user_one = 1 AND (
  (a.user_two = b.user_one AND b.user_two = c.user_id) OR
  (a.user_two = b.user_two AND b.user_one = c.user_id)
  ) OR (a.user_two = 1 AND (
  (a.user_one = b.user_one AND b.user_two = c.user_id) OR
  (a.user_one = b.user_two AND b.user_one = c.user_id)
  )
 )) AND c.user_id != 1 AND
 c.user_id NOT IN (
   SELECT friends.user_two FROM friends WHERE friends.user_one = 1 UNION
   SELECT friends.user_one FROM friends WHERE friends.user_two = 1
 )
ORDER BY c.`user_id` ASC

我相信这应该链接到正确的 sqlfiddle:http ://sqlfiddle.com/#!2/6c14e/2

于 2013-09-21T13:07:28.687 回答