繁体   English   中英

在不同的表上加入两个类似的查询 - MySQL OR

[英]Joining two similar queries on different tables- MySQL OR

我遇到了MySQL查询的麻烦(我是新手,所以对我来说很容易!)。 我有一个有电视节目的网站,想要根据两个不同的动作(自定义时间表)选择两个日期之间播出的剧集(没问题)。 基本上,如果用户正在关注(uses_follow_shows)或观看节目(user_watched),我想要显示剧集,所以我认为我会(如下所示)(query_on_follow或query_on_watch),但这不起作用(我得到1200行而不是3,它从user_watched获取每个现有行。

我认为这个说法会做,但它没有,我不明白为什么

SELECT * FROM show_episode_airdate, show_episode, show_network, network, shows, users_follow_shows, user_watched
                                              WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' 
                                              AND ( show_episode.episode_id = show_episode_airdate.episode_id 
                                              AND shows.id = show_network.show_id
                                              AND show_network.network_id = network.network_id 
                                              AND show_episode.imdb_id_show = shows.imdb_id 
                                              AND users_follow_shows.user_id = 2 AND shows.id = users_follow_shows.show_id  

                                              OR user_watched.user_id = 2 
                                              AND shows.id = user_watched.show_id 
                                              AND show_episode.episode_id = show_episode_airdate.episode_id 
                                              AND shows.id = show_network.show_id
                                              AND show_network.network_id = network.network_id 
                                              AND show_episode.imdb_id_show = shows.imdb_id )
                                              ORDER by network.network_id ASC

谁能告诉我什么是错的?

谢谢!

编辑:

SELECT *
 FROM show_episode_airdate join
 show_episode 
 on show_episode.episode_id = show_episode_airdate.episode_id join
 shows
 on shows.imdb_id = show_episode.imdb_id_show join
 show_network
 on show_network.show_id = shows.id join
 network
 on show_network.network_id = network.network_id join
 users_follow_shows
 on shows.id = users_follow_shows.show_id join
 user_watched
 on shows.id = user_watched.show_id 
WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' and
  (users_follow_shows.user_id = 2  or
   user_watched.user_id = 2
  )
 ORDER by network.network_id ASC;

如果用正确的连接语法编写它,那么逻辑问题就会消失。 结果看起来像这样:

SELECT *
FROM show_episode_airdate join
     show_episode 
     on show_episode.episode_id = show_episode_airdate.episode_id join
     show_network 
     on show_network.show_id = network.show_id join     <------- THIS IS NOT IN YOUR ORIGINAL LIST
     network
     on show_network.network_id = network.network_id join
     user_follows_shows
     on shows.id = users_follow_shows.show_id join
     user_watched
     on shows.id = user_watched.show_id 
WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' and
      (users_follow_shows.user_id = 2  or
       user_watched.user_id = 2
      )
ORDER by network.network_id ASC;

有什么好处? 查询更易理解,更容易理解,更容易理解,更不容易犯错误,例如遗漏连接条件。 SQL引擎可以更轻松地优化它,它应该运行得更快。 使用正确的连接语法。

好像要强调我的观点,原始查询有7个表,但只有5个连接条件。 这通常意味着您在表之间进行笛卡尔积。 在这种情况下,我相信它缺少show_networkshows之间的关系。

编辑:

至少现在,查询是可以理解的。 问题是用户可能会关注一些节目并观看一些节目。 您的查询是在这两组之间生成笛卡尔积。 更糟糕的是,如果一个节目没有粉丝或没有观众,那么它就会辍学。

解决问题的一种方法是将查询拆分为两个。 相反,我将在select子句中使用left outer joindistinct

SELECT distinct *
 FROM show_episode_airdate join
 show_episode 
 on show_episode.episode_id = show_episode_airdate.episode_id join
 shows
 on shows.imdb_id = show_episode.imdb_id_show join
 show_network
 on show_network.show_id = shows.id join
 network
 on show_network.network_id = network.network_id left outer join
 users_follow_shows
 on shows.id = users_follow_shows.show_id left outer join
 user_watched
 on shows.id = user_watched.show_id 
WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' and
  (users_follow_shows.user_id = 2  or
   user_watched.user_id = 2
  )
 ORDER by network.network_id ASC;

*应该替换为您实际需要的列 - 而distinct只有在您避开users_follow_showsuser_watchedusers_follow_shows user_watched left outer join意味着将考虑所有节目。

另一种编写方法 - 在select子句中不需要distinct - 就是编写一个子查询来组合观察和跟随的节目。 这将删除重复项,如下所示:

SELECT *
FROM show_episode_airdate join
     show_episode 
     on show_episode.episode_id = show_episode_airdate.episode_id join
     shows
     on shows.imdb_id = show_episode.imdb_id_show join
     show_network
     on show_network.show_id = shows.id join
     network
     on show_network.network_id = network.network_id join
     (select show_id, user_id
      from users_follow_shows
      union
      select show_id, user_id
      from user_watched
     ) watch_or_follow
     on shows.id = watch_or_follow.show_id
WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' and
      watch_or_follow.user_id = 2
ORDER by network.network_id ASC;

你需要为OR条件put () ,例如,如果这是你的目标:

SELECT * FROM show_episode_airdate, show_episode, show_network, network, shows, users_follow_shows, user_watched
WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' 
AND ( (show_episode.episode_id = show_episode_airdate.episode_id 
AND shows.id = show_network.show_id
AND show_network.network_id = network.network_id 
AND show_episode.imdb_id_show = shows.imdb_id 
AND users_follow_shows.user_id = 2 
AND shows.id = users_follow_shows.show_id)
OR (user_watched.user_id = 2 
AND shows.id = user_watched.show_id 
AND show_episode.episode_id = show_episode_airdate.episode_id 
AND shows.id = show_network.show_id
AND show_network.network_id = network.network_id 
AND show_episode.imdb_id_show = shows.imdb_id ) )
ORDER by network.network_id ASC

所以你会得到: IF BETWEEN日期AND第一(条件) OR第二(条件)之间

我建议你使用JOIN / INNER JOIN ,我迷失在所有这些AND中:D

这是由于您在where子句中使用的OR条件。 对组合条件给予适当的限制。

只需尝试以下查询即可。

SELECT * FROM show_episode_airdate, show_episode, show_network, network, shows, users_follow_shows, user_watched
WHERE show_episode_airdate.airdate BETWEEN '2013-07-20' AND '2013-07-27' 
 AND (( show_episode.episode_id = show_episode_airdate.episode_id 
 AND shows.id = show_network.show_id
 AND show_network.network_id = network.network_id 
 AND show_episode.imdb_id_show = shows.imdb_id 
 AND users_follow_shows.user_id = 2 AND shows.id = users_follow_shows.show_id  )
OR (user_watched.user_id = 2 
AND shows.id = user_watched.show_id 
AND show_episode.episode_id = show_episode_airdate.episode_id 
AND shows.id = show_network.show_id
AND show_network.network_id = network.network_id 
AND show_episode.imdb_id_show = shows.imdb_id ))

ORDER by network.network_id ASC

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM