Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/sql/85.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Mysql SQL-连接更多表而不是(子查询)_Mysql_Sql - Fatal编程技术网

Mysql SQL-连接更多表而不是(子查询)

Mysql SQL-连接更多表而不是(子查询),mysql,sql,Mysql,Sql,我有一个users表-包含id\u user和一些其他列…然后还有一些其他表存储用户连接,这些连接总是与结构id\u user\u one、id\u user\u two、active一起使用,其中用户可以是id\u user\u one或id\u user\u two。还请注意,在每个连接表中,两个用户之间可以有连接,例如,朋友表中的一条记录和家庭表中的一条记录 这里有一个表,表中有posts id\u post,id\u user,…其他一些列 所以现在我想获取特定用户和与他相关的用户的所有

我有一个users表-包含id\u user和一些其他列…然后还有一些其他表存储用户连接,这些连接总是与结构id\u user\u one、id\u user\u two、active一起使用,其中用户可以是id\u user\u one或id\u user\u two。还请注意,在每个连接表中,两个用户之间可以有连接,例如,朋友表中的一条记录和家庭表中的一条记录

这里有一个表,表中有posts id\u post,id\u user,…其他一些列

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

到目前为止,我知道213是一个特殊的id_用户,示例连接表是朋友和家人,但可能会有更多

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
)
这是可行的,但我的问题是如何使用联接而不是INsubquery来实现这一点

或者,对于这种情况,使用INsubquery是一种更有效的方法吗

编辑:我在原始查询中出错:

(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)
……家庭部分也是如此……因此,了解了这一点,并根据公认的答案,我成功地进行了最后的查询,我想分享这些知识,以便:

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


只需为查询指定一个名称:

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

以下是一个mpre高效查询:

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
             );
然后,在friendsid_user、active、id_user_one、id_user_two上有一个索引,在family上有一个类似的索引,这个查询将更加高效。这些索引覆盖了查询,因此不需要原始数据页,只需要索引

在where子句中切换到ors而不是union会给您带来一些好处。首先,不必返回整个结果即可获得匹配。第二,条件短路,因此第一个匹配条件结束比较。第三,也是最重要的一点,引擎可以利用表上的索引

我认为,如果表被正确地索引,那么尝试创建联接不会更好

将自然联接更改为联接不会影响性能。我只是不喜欢自然连接,因为你看不到连接条件——随着时间的推移,会导致代码维护问题

编辑:

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

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)
             );

哪里有。。。顺便说一句:UNION返回唯一的结果。因为除了IN子句之外,您没有将这些结果用于其他任何内容,所以没有理由不使用UNION ALL,这应该会快一点。@Mureinik所以您认为在IN中有重复项比先删除这些重复项更快?@jave.web如果IN实现正确并且在第一次出现时提前返回,那么应该是这样的。话虽如此,我并没有在任何最新的MySQL版本上对此进行基准测试。我修改了内部查询-联合,但@Gordon Linoff的回答涵盖了实际问题,但仍然非常感谢。你可能是对的!我在那里输入了一个错误-id\u用户从朋友中选择应该是id\u用户作为id\u用户-无论如何你是对的,这是错误的-应该有一个联盟覆盖其他可能性这不会正常工作,而且我不确定其他事情是否是由我添加的额外查询引起的,至于答案,这是对这个问题的回答:对你的编辑:是的,有点像那样,但有点不同-见我的编辑:,PS:删除无用的评论
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)
             );