【问题标题】:select multiselect values using group_concat and left join使用 group_concat 和左连接选择多选值
【发布时间】:2018-01-08 11:07:22
【问题描述】:

所以我正在使用 PHP 和 MySQL 制作一个简单的电影数据库。我有两张桌子:

电影

身份证 |标题 |类型 ----------------------------------------- 1 |黑暗骑士 | 1,2 2 |钢铁侠 | 3,4 3 |蜘蛛侠 | 5,6

电影类型

身份证 |类型 ---------------------- 1 |行动 2 |冒险 3 |动画片 4 |传 5 |喜剧 6 |犯罪

这是我的查询

选择电影。*,GROUP_CONCAT(moviesgenre.genre) 作为流派 从电影 左加入 moviesgenre ON movies.genre = moviesgenre.id

这是我目前得到的结果:

身份证 |标题 |类型 |流派 ------------------------------------------ 1 |黑暗骑士 | 1,2 |动作,动画,喜剧

我期望的输出:

身份证 |标题 |类型 |流派 ------------------------------------------ 1 |黑暗骑士 | 1,2 |动作,冒险 2 |钢铁侠 | 3,4 |动画,传记 3 |蜘蛛侠 | 5,6 |喜剧,犯罪

这可能吗?如果可以,怎么做?

【问题讨论】:

  • 你期望什么输出?
  • 查看规范化并相应地修改您的架构。

标签: mysql left-join


【解决方案1】:

根据实体关系数据库规则,您应该为所需的多对多关系向数据库添加一个表,并修改您的电影表:

电影

ID  | Title             
-----------------------------
1   | The Dark Knight 
2   | Man of steel    
3   | SpiderMan      

电影_流派

Movie_ID  | Genre_ID    
-----------------------------
1   | 1
1   | 2
2   | 3
2   | 4
3   | 5
3   | 6

类型

ID  | genre    
------------------------
1   | Action
2   | Adventure
3   | Animation
4   | Biography
5   | Comedy
6   | Crime

然后SQL变成:

   SELECT Movies.*, GROUP_CONCAT(Genres.ID), GROUP_CONCAT(Genres.genre)
   FROM   Movies INNER JOIN 
          Movies_Genre ON Movies.ID = Movies_Genre.Movie_ID 
   INNER JOIN Genres ON  Movies_Genre.Genre_ID = Genres.ID
   GROUP BY Movies.ID

您可以在 WHERE 子句中使用 FIND_IN_SET 语句:

SELECT movies.*,
       GROUP_CONCAT(moviesgenre.genre) as genres
FROM movies, genre
WHERE FIND_IN_SET(moviesgenre.ID, Movies.genre)>0
GROUP BY Movies.ID

但是这个解决方案并不推荐,因为当你的数据库大小增加时,你会遇到性能下降,并遇到其他困难。

【讨论】:

  • @Strawberry 滥用downvotes 等于滥用SQL。我是批准您的规范化建议的人,但是 FIND_IN_SET 和 GROUP_CONCAT 是 MySQL 中可用的函数。为什么我们不必使用它们并了解它们是否适合我们的目的和上下文?
  • @Strawberry 好的,你可能是对的,我将添加所需的规范化
  • 我仍然对 GROUP_CONCAT 有疑问,但我接受这正确满足要求。
【解决方案2】:

你可以使用MySQL函数FIND_IN_SET来实现你想要的。您还需要按电影对查询进行分组。

I've set up this SQL Fiddle 展示如何实现它。

您的查询最终将如下所示:

SELECT movies.*, GROUP_CONCAT(moviegenres.genre) AS genre
FROM movies    
LEFT JOIN moviegenres ON FIND_IN_SET(moviegenres.id, movies.genre)
GROUP BY movies.id

【讨论】:

  • 感谢您的反对。如果您觉得答案有问题,请发表评论。
  • 这对他的问题有何帮助?它为 OP 提供了他尝试构建的查询的预期结果,并参考了有关已实现代码的文档。
  • OP 误解了关系数据库管理的基本概念,即规范化。任何未能解决此问题的答案只会使错误永久存在。
  • 非常感谢,就像魅力一样,再次投反对票的不是我
  • 和仅供参考,我不能投票,因为少了 15 个声望
【解决方案3】:

您必须在电影表的流派列表中加入流派 id 上的两个表。将在流派名称上进行组连接。这是查询:

SELECT A.ID, A.Title, A.Genre, GROUP_CONCAT(DISTINCT B.GENRE SEPARATOR ',') GenreNames
FROM Movies A LEFT JOIN moviesgenre B
ON LOCATE(B.ID,A.Genre) > 0
GROUP BY A.ID, A.Title, A.Genre;

更多信息见:

MySQL LOCATE() Function

MySQL GROUP_CONCAT Function

【讨论】:

  • 请留下评论为什么您认为我的回答是错误的,不要简单地投反对票。
猜你喜欢
  • 2019-05-19
  • 1970-01-01
  • 1970-01-01
  • 2016-12-06
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-11-28
  • 2016-02-27
相关资源
最近更新 更多