2012-04-26 44 views
0

我有两个表:UserUser2Friend。我需要得到用户的朋友。查询应该处理两列FriendId:FriendIdUserId,因为我们不知道谁加了谁。结果都是朋友。获取用户朋友,子查询,性能

查询:

SELECT DISTINCT 
    `Id` 
    , `UserName` 
FROM `User` 
WHERE `Id` IN 
    (SELECT 
     IF(`UserId` = 25, `FriendId`, `UserId`) -- This important part - friends are always mutual 
    FROM `User2Friend` 
    WHERE `UserId` = 25 
    OR `FriendId` = 25) 
LIMIT 10 

的模式:

CREATE TABLE `User` (
    `Id` int(10) unsigned NOT NULL AUTO_INCREMENT, 
    `UserName` varchar(16) DEFAULT NULL, 
    PRIMARY KEY (`Id`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 
CREATE TABLE `User2Friend` (
    `Id` int(11) unsigned NOT NULL AUTO_INCREMENT, 
    `UserId` int(10) unsigned NOT NULL, 
    `FriendId` int(10) unsigned NOT NULL, 
    PRIMARY KEY (`Id`), 
    UNIQUE KEY `UserIdFriendId` (`UserId`, `FriendId`) 
) ENGINE=InnoDB DEFAULT CHARSET=utf8; 

如果用户A加入用户B的好友,用户B出现在用户的朋友列表,用户B后,必须有用户A在朋友列表中。我不太喜欢子查询方法,因为我不能在子选择中使用LIMIT。

我期待数百万用户,所以表现很重要。

你认为将这个查询拆分为两个单独的更好吗?

或者我需要有棘手的JOIN?

+0

你可以把你的表的结构 – 2012-04-26 05:46:55

+0

在这里你是...^ – 2012-04-26 05:57:05

回答

0

好吧!我把它分成两个查询...

0
$sql1 = ("SELECT Id, UserName FROM User WHERE UserId = 25"); 
foreach($sql1 as $row){ 
    $id  = $row['Id']; 
    $name = $row['UserName']; 
     $sql2 = ("SELECT * FROM User2Friend WHERE FriendId = $id LIMIT 10"); 
     foreach($sql2 as $row){ 
      $FriendId = $row['FriendId']; 
      $FriendName = $row['FriendName']; 
     } 
} 

我不知道我是否理解得很好,但看看是否解决了这个问题。

+0

1.你的例子是错误的,因为你首先选择Id 25而不是所有的朋友ID。实际上,你必须考虑查找表中的两列:FriendId和UserId。取决于谁添加了谁...... – 2012-04-26 05:06:37

0

您在User2Friend表中创建第三个字段(默认值为N),当添加好友B时,它将能够列出这个好友,并且可以确认(S)并接受友谊。

+0

不需要添加'User2Friend'表中的字段已接受朋友。 – 2012-04-26 11:59:46