【问题标题】:Many-to-many query, MySQL多对多查询,MySQL
【发布时间】:2011-12-29 02:10:28
【问题描述】:

我有 3 个这样的表:

电影:

  • movie_id (int)
  • movie_title (varchar)
  • movie_runtime (int)
  • movie_releaseYear (int)
  • ...

类型:

  • genre_id (int)
  • genre_name (varchar)

电影流派:

  • movieGenre_id (int)
  • movieGenre_movieId (int)
  • movieGenre_genreId (int)

一部电影可以包含多种类型。
我想获取电影名称、运行时间和发行年份及其类型。如何在单个查询中做到这一点?

我试着这样做:

SELECT u.movie_title, u.movie_runtime, u.movie_releaseYear, a.genre_name 
FROM movieGenres ua 
LEFT JOIN movies u ON u.movie_id = ua.movieGenre_filmId 
LEFT JOIN genres a ON a.genre_id = ua.movieGenre_genreId
LIMIT 0,10

这会返回类似:

罗宾汉 _ 101 _ 2001 _ 冒险
罗宾汉 _ 101 _ 2001 _ 动作
罗宾汉 _ 101 _ 2001 _ 戏剧
防火墙 _ 98 _ 2003 _ 行动
防火墙 _ 98 _ 2003 _ 剧情

我不想重复我已经知道的信息。我希望它像这样显示:

罗宾汉 _ 101 _ 2001 _ 冒险 _ 动作 _ 剧情
防火墙_98_2003_动作_剧情

请帮我解决这个问题:)

【问题讨论】:

    标签: mysql database many-to-many


    【解决方案1】:

    几周前我遇到了这个问题,我的教授给了我一个非常聪明的解决方案:

    在子查询中使用 Group_Concat 函数以逗号分隔值的形式获取结果,然后使用explode/split/任何相当于循环遍历 CSV 结果的语言。

    http://mahmudahsan.wordpress.com/2008/08/27/mysql-the-group_concat-function/

    希望这会有所帮助!这个问题让我沮丧了一阵子,但我认为这是最简单的解决方案。

    【讨论】:

      【解决方案2】:

      这就是数据库的工作方式。有'有'方法可以做你想做的事,但老实说,数据库通常不是完成它的正确位置。这纯粹只是一个临时查询,还是这些结果会发送给应用程序?如果是这样,该应用程序将是按照您希望的方式格式化结果的正确位置。

      【讨论】:

      • 我不同意,数据库是执行此操作的理想场所,因为它减轻了客户端的一些处理负载。
      • @MichaelEakins 看看我们在这里处理的数据的性质。您真的认为客户会在速度成为问题的情况下对这些数据进行任何处理吗?另一方面,如果这是在处理大量请求的 Web 服务器上(例如 IMDB),那么您会想要将处理移至客户端。 -1 对您盲目地做出一揽子陈述的评论,该陈述既可能是错误的,也可能是真实的。
      • touche,我们在某一方面都是正确的,然后是 winform vs web。
      • Web vs WinForm 并不是问题所在,尽管我知道您来自哪里。您要问的第一个问题是,是否甚至需要为了性能而费心分配工作负载。如果不需要,您不会主动为此浪费开发时间,尤其是在这种情况下,因为应用程序比数据库更适合格式化数据。如果有需要,您可以根据需要分发它,虽然 Web 应用程序的容量往往高于 WinForm 应用程序,但情况并非如此。
      • 这么简单,他只好来请教写了,对吧?哈哈 :) 当您将 SQL 用于它的设计用途时,编写它并不难。它不是为格式化而设计的。这不仅仅是关于哪个地方更容易格式化数据。这是关于如果您需要将此数据用于其他任何事情(或先取消格式化),您现在必须如何重新查询数据库。这就是存在业务对象的原因。我是说他的方法绝对错误吗?如果这是一个不会做任何其他事情的包含项目,也许不会。但如果它要成长并做得更多,可能会如此。
      【解决方案3】:
      SELECT
          u.movie_title,
          u.movie_runtime,
          u.movie_releaseYear,
          GROUP_CONCAT(a.genre_name) genre
      FROM
          movieGenres ua  
          INNER JOIN movies u ON u.movie_id = ua.movieGenre_filmId  
          INNER JOIN genres a ON a.genre_id = ua.movieGenre_genreId
      GROUP BY
          u.movie_title,
          u.movie_runtime,
          u.movie_releaseYear
      LIMIT 0,10 
      ;
      

      这本质上是您的查询。我刚刚添加了GROUP BY 子句和GROUP_CONCAT 函数。默认分隔符是逗号 (,)。如果您想要以空格分隔的流派列表,请使用 GROUP_CONCAT 函数:

      SELECT
          u.movie_title,
          u.movie_runtime,
          u.movie_releaseYear,
          GROUP_CONCAT(a.genre_name SEPARATOR ' ') genre
      FROM
          movieGenres ua  
          INNER JOIN movies u ON u.movie_id = ua.movieGenre_filmId  
          INNER JOIN genres a ON a.genre_id = ua.movieGenre_genreId
      GROUP BY
          u.movie_title,
          u.movie_runtime,
          u.movie_releaseYear
      LIMIT 0,10
      ;
      

      【讨论】:

      • 谢谢!这真的帮助了我:)
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-08-17
      • 1970-01-01
      • 1970-01-01
      • 2019-12-09
      • 1970-01-01
      • 2017-06-29
      相关资源
      最近更新 更多