SQL - 加入更多表而不是IN(子查询)

时间:2014-02-08 16:20:51

标签: mysql sql

我有一个用户表 - 包含id_user和其他一些列...然后是一些其他表存储用户连接的表,这些表始终使用结构id_user_one, id_user_two, active,其中user可以是{ {1}}或id_user_one。另请注意,每个连接表中有2个用户可以建立连接(例如,朋友表中的一个记录和族表中的一个记录),

还有一个包含帖子的表格(id_user_two),

所以现在我想获得与他有关的特定用户和用户的所有帖子。

到目前为止,我有这个(213是一个特定的id_user),(示例连接表是朋友和家人,但可能会有更多)

id_post, id_user, ...some other columns

它正在运作,但我的问题是如何使用SELECT * FROM posts NATURAL JOIN users WHERE id_user IN ( SELECT * FROM( (SELECT 213 as id_user) UNION (SELECT id_user FROM friends WHERE (id_user_one=213 OR id_user_two=213) AND active=1) UNION (SELECT id_user FROM family WHERE (id_user_one=213 OR id_user_two=213) AND active=1) ) idList ) 代替JOIN

或者在这种情况下使用IN(子查询)更有效的方法吗?

编辑:我在原始查询中犯了错误:

IN(subquery)

应该是:

(SELECT id_user FROM friends WHERE (id_user_one=213 OR id_user_two=213) AND active=1)

......同样适用于“家庭”部分...所以有了这个知识,并根据接受的答案,我设法做了我的最后查询,我想分享知识,所以:

以下是我的最终解决方案:

(SELECT id_user_two as id_user FROM kontakty WHERE id_user_one=213 AND active=1)
    UNION 
(SELECT id_user_one as id_user FROM kontakty WHERE id_user_two=213 AND active=1)

2 个答案:

答案 0 :(得分:1)

这是一个有效的查询:

SELECT *
FROM posts p JOIN
     users u
     on p.id_user = u.id_user
WHERE u.id_user = 213 or
      exists (select 1
              from friends f
              where (f.id_user_one=213 OR f.id_user_two=213) and f.active = 1 and
                    u.id_user = f.id_user
             ) or
      exists (select 1
              from family f
              where (f.id_user_one = 213 OR f.id_user_two = 213) and f.active = 1 and
                    u.id_user = f.id_user
             );

然后,使用friends(id_user, active, id_user_one, id_user_two)上的索引和family上的类似索引,此查询将更有效。这些索引“覆盖”了查询,因此不需要原始数据页,只需要索引。

切换到or子句中的where而不是union会给您带来好处。首先,不必返回整个结果以获得匹配。其次,条件是“短路的”,因此第一个匹配条件结束比较。第三(也是最重要的),引擎可以利用桌面上的索引。

如果表格被正确编入索引,我认为尝试创建join会更好。

natural join更改为join不会影响效果。我不是natural join的粉丝,因为您无法看到join条件 - 导致代码中的维护问题。

编辑:

我怀疑这是您想要的查询:

SELECT *
FROM posts p JOIN
     users u
     on p.id_user = u.id_user
WHERE u.id_user = 213 or
      exists (select 1
              from friends f
              where (f.id_user_one=213 OR f.id_user_two=213) and f.active = 1 and
                    (u.id_user = f.id_user_one or u.id_user = f.id_user_two)
             ) or
      exists (select 1
              from family f
              where (f.id_user_one = 213 OR f.id_user_two = 213) and f.active = 1 and
                    (u.id_user = f.id_user_one or u.id_user = f.id_user_two)
             );

答案 1 :(得分:0)

只需为查询命名:

SELECT * 
FROM posts 
NATURAL JOIN users 
JOIN (SELECT * FROM(
        (SELECT 213 as id_user)
        UNION
        (SELECT id_user FROM friends WHERE (id_user_one=213 OR id_user_two=213) AND active=1)
        UNION
        (SELECT id_user FROM family WHERE (id_user_one=213 OR id_user_two=213) AND active=1)
     ) idList ON idList.id_user = users.id_user