问题是从许多小问题做出一个大的查询

时间:2011-08-01 14:45:01

标签: mysql sql

我遇到了一个问题,我可以通过php和一些查询轻松解决,但我想做一个大问题(至少如果它更快,我认为应该是这样)。

所以我有3个表,让我们简化一些:

topic有3列

  • ID
  • user_id
  • 能见度

access有2列

  • topic_id
  • USER_ID

friendship有2列

  • user_id
  • friend_id

我想要做的是,如果用户(我们称他为watch_id)正在尝试观看此主题,我想在允许观看的情况下返回主题,或者如果他不是,则不返回任何内容。 他被允许观看其中任何一个是否属实

  • watch_id == user_id
  • visibility == 3
  • visiblity == 2&&友谊表返回一行,当friendship.user_id = topic.user_id&& friendship.friend_id == watch_id
  • visibility == 1&& access.topic_id = topic.id&&amp ;;访问表返回一行。 access.user_id == watch_id

正如你所看到的,使用php和一堆查询并不是很难,但在sql中,我无法弄明白。我一直在尝试连接,案例和东西,但逻辑永远不会加起来。 :(

那么你们可以帮助我吗?或者我坚持使用php和大量查询?

编辑:嗯,看起来我并没有让自己完全清楚,我的坏!他被允许观察是否有任何这些要求是真的。由于这种情况,我选择左连接答案,这是最容易扩展的。谢谢大家!

4 个答案:

答案 0 :(得分:3)

您应该能够对友谊和访问表进行左连接,以便连接本身不会限制结果:

select something
from topic
left join friendship on friendship.user_id = topic.user_id && friendship.friend_id == watch_id
left join access on access.topic_id = topic.id && access.user_id == watch_id
where
  watch_id == topic.user_id or
  topic.visibility == 3 or
  (topic.visiblity == 2 and friendship.user_id is not null) or
  (visibility == 1 && access.topic_id is not null)

答案 1 :(得分:0)

这可以通过一个查询实现,但最简单的方法是使用UNION来合并不同要求的结果。

SELECT t.*
FROM   topic AS t
WHERE  t.user_id = @watch_id AND t.visibility = 3
UNION ALL
SELECT t.*
FROM   topic AS t
       INNER JOIN friendship AS f ON f.user_id = t.user_id
WHERE  f.friend_id_id = @watch_id AND t.visibility = 2
UNION ALL
SELECT t.*
FROM   topic AS t
       INNER JOIN access AS a ON a.topic_id = t.id
WHERE  a.user_id = @watch_id AND t.visibility = 1

答案 2 :(得分:0)

如果您有三个单独的查询返回您需要的内容,那么您可以考虑在三个结果集上执行联合以获取所需的主题。

基本上,以下内容可以让您返回用户可以观看的所有主题的列表。

select t.topic_id
from   topic as t
where  t.user_id = watch_id
and    t.visibility = 3
  union
select t.topic_id
from   topic as t
inner join friendship as f
on     f.user_id = t.user_id
where  f.friend_id = watch_id
and    t.visibility = 2
  union
select t.topic_id
from   topic as t
inner join access as a
on     a.topic_id = t.id
where  a.user_id = watch_id
and    t.visibility = 1

你应该能够用它来获得你所需要的东西。

如果您需要一个可以确认是否可以监视给定topic_id的过程或函数,那么您可以查看是否在上述结果集中包含topic_id

答案 3 :(得分:0)

尝试子查询:

select topic.* from topic
where (topic.user_id = watch_id and visibility=3) or 
      (topic.user_id = watch_id and visibility=2 and (select count(*) from friendship where friendship.user_id = topic.user_id and friendship_id = watch_id) > 0) or
      (topic.user_id = watch_id and visibility=1 and (select count(*) from access where access.topic_id = topic.id and access.user_id = watch_id) > 0)

即使存在多个友谊或访问条目,此解决方案也允许单个主题。看看你的问题,我假设topic.user_id必须等于所有三个的watch_id,但我可能错了。

但是,如果三个表之间只存在一对一的关系,那么左连接是可行的方法。