我有一个用户表 - 包含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)
答案 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