如何在一个查询中选择自己的朋友条目和条目

时间:2013-11-07 13:23:14

标签: mysql sql join union

我经常遇到这样的数据库查询:

  

获取userX的所有条目(例如评论)以及userX的朋友的所有条目

这是在SQL(MySQL)中执行此操作的最佳方法,假设userX不是他自己的朋友。

1。进行两次查询,稍后将其与PHP

合并
a = SELECT *
    FROM comments
    WHERE user = X
b = SELECT c.*
    FROM comments c
    INNER JOIN relation r ON r.user2 = c.user
    WHERE r.user1 = X
merge(a, b)

这就是我通常所做的。它性能相当高,但我不能使用ORDER BY或LIMIT

2。 IN和UNION的子查询

SELECT c.*
FROM comments
WHERE user IN (
    SELECT "X"
    UNION
    SELECT user2 FROM relation WHERE user1 = X
)

这似乎很慢,因此一个坏主意,不是吗?

第3。其他方案?有条件的加入或某事......

3 个答案:

答案 0 :(得分:0)

为什么不:

SELECT c.*
FROM comments
WHERE user = X OR user IN (
    SELECT user2 FROM relation WHERE user1 = X
)

如果这很慢,你应该看一下执行计划。您可能缺少索引。

答案 1 :(得分:0)

执行此操作的一种方法是从用户表启动查询。加入关系表。然后,您可以使用条件“ON”语句加入对此的注释。这样MySQL可以使用索引。

select c.* from users a
left outer join relation friend on a.id = friend.user1_id
join comments c on (c.user_id = a.id or c.user_id = friend.user2_id)
where a.id = 1
group by c.id;

以下是一个有效的例子:http://sqlfiddle.com/#!2/da298/1

答案 2 :(得分:0)

你的#2没有任何问题。您很可能没有所需的索引。

作为一个学术案例研究,以下是应该返回相同结果集的各种表单。你应该用EXPLAIN尝试每一个,并看看哪个最适合你(确保正确的索引在那里)(我偏向第三个,因为我发现它表现得一样好,如果不是更好它和它允许多个字段相关。您可以搜索SO或Google以获取有关IN vs EXISTS的MySQL性能的文章

UNION结果 - 这是你的#1的改进版本;数据在MySQL中仍然是UNIONed,而不是PHP

SELECT *
FROM comments
WHERE user = X
UNION
SELECT c.*
FROM comments c
INNER JOIN relation r 
  ON r.user2 = c.user
WHERE r.user1 = X

您的选项#2 - IN

SELECT c.*
FROM comments
WHERE user IN (
    SELECT "X"
    UNION
    SELECT user2 FROM relation WHERE user1 = X) 

<强> EXISTS

一般来说,我更喜欢IN,因为它允许多个字段相关

SELECT c.*
FROM comments AS c
WHERE c.user = X
   OR EXISTS(SELECT *
             FROM relation AS r
             WHERE r.user1 = X
                AND r.user2 = c.user)