在PHP中使用group_concat回显mysql数据

在PHP中使用group_concat回显mysql数据,php,mysql,Php,Mysql,这是我的SQL小提琴: 我试图用PHP来回应这个结果。这是我的预期结果: // Some Stuff Here The Dark Knight Rises - 7.5 Batman Begins - 7.5 Iron Man - 7.3 The Lord of the Rings: The Return of the King - 8.1 etc... // Some more Stuff here 我的PHP代码: $stmt = $conn->prepare("SELECT

这是我的SQL小提琴:

我试图用PHP来回应这个结果。这是我的预期结果:

// Some Stuff Here

The Dark Knight Rises -  7.5
Batman Begins - 7.5 
Iron Man - 7.3
The Lord of the Rings: The Return of the King - 8.1 
etc...

// Some more Stuff here
我的PHP代码:

$stmt = $conn->prepare("SELECT tmdb_movies.movie_title
,GROUP_CONCAT(recommendations.recommendations_title  ORDER BY recommendations.recommendations_title) as recommendations_title
,GROUP_CONCAT(recommendations.recommendations_vote_average ORDER BY recommendations.recommendations_title) as recommendations_vote_average

FROM tmdb_movies 

LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id
LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id


Where tmdb_movies.tmdb_id= 155

GROUP BY tmdb_movies.movie_title
 ");


     // Then fire it up
     $stmt->execute();
     // Pick up the result as an array
     $result = $stmt->fetchAll();

    // Now you run through this array in many ways, for example
     for($x=0, $n=count($result); $x < $n; $x++){
$recommendations_name_list = explode(',',$result[$x]["recommendations_title"]);
$recommendations_vote_average = explode(',',$result[$x]["recommendations_vote_average"]);
foreach( $recommendations_name_list as $index => $recommendations_title ) {
           echo'
    <p>'.$recommendations_title.'- '.$recommendations_vote_average[$index].'</p>';
    }
}
但是如果我删除这一行
LEFT JOIN cast ON cast.cast\u tmdb\u id=tmdb\u movies.tmdb\u id
那么,我的php代码工作正常

预期结果:

Batman Begins- 7.5

Captain America: The First Avenger- 6.6

Inception- 8

Iron Man- 7.3

Iron Man 2- 6.6

The Dark Knight Rises- 7.5

The Lord of the Rings: The Fellowship of the Ring- 8

The Lord of the Rings: The Return of the King- 8.1

The Lord of the Rings: The Two Towers- 7.9

The Matrix- 7.9

左连接强制转换的使用

对于select值不可用(结果是select ayway,因为它们基于maun表格电影标题 adn不返回有用的信息,因为select子句中没有di table中的列)并生成包含更多行的结果集

所以,如果您想坚持这个左连接,您可以将DISTINCT添加到原始查询中

 SELECT DISTICNT 
  tmdb_movies.movie_title
  ,GROUP_CONCAT(recommendations.recommendations_title  
        ORDER BY recommendations.recommendations_title) as recommendations_title
  ,GROUP_CONCAT(recommendations.recommendations_vote_average 
      ORDER BY recommendations.recommendations_title) as recommendations_vote_average

FROM tmdb_movies 

LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id
LEFT JOIN recommendations 
    ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id
Where tmdb_movies.tmdb_id= 155
GROUP BY tmdb_movies.movie_title
或者最好不要使用左连接pn强制转换

   SELECT 
    tmdb_movies.movie_title
    ,GROUP_CONCAT(recommendations.recommendations_title  
          ORDER BY recommendations.recommendations_title) as recommendations_title
    ,GROUP_CONCAT(recommendations.recommendations_vote_average 
        ORDER BY recommendations.recommendations_title) as recommendations_vote_average

  FROM tmdb_movies 


  LEFT JOIN recommendations 
      ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id
  Where tmdb_movies.tmdb_id= 155
  GROUP BY tmdb_movies.movie_title

在你的帖子里有很多东西是不符合逻辑的。您的sql FIDLE完全缺少强制转换表。我已经评论过你不恰当地使用了GROUP_CONCAT。您的问题没有完整的信息来帮助我们了解您的问题

话虽如此,我相信我已经猜到了一些接近你真正想要的东西。主要的问题是,您的群组成员应该同时包含原始电影和推荐的电影。这将为每组电影/推荐组合返回一行。您可以使用GROUP_CONCAT在一个列中进行转换。此外,我认为您想要的演员数据实际上是推荐电影的演员,而不是原始电影的演员。您可以将两者结合在一起,但在本查询的上下文中,我认为您可能希望将推荐电影的演员组合与GROUP_CONCAT合并到一个专栏中。正如我向您评论的那样,问题在于推荐表中没有推荐电影的tmdb_id。坦率地说,这是一个非规范化的结构(存储标题而不是id),并且在关系上是不正确的、浪费的和潜在的混乱

为什么会这样

首先,推荐表没有主键,它需要一个主键。片名也不是一个很好的候选关键,因为有很多电影都有相同的片名。在您的系统中,无法确定几部电影中哪部可能具有相同的标题。因此,您应该将tmdb_id作为外键,在这一点上,您不需要(也不想要)标题,因为它可以从tmdb_movies表中获得。您的推荐表本质上是一个多对多表,它以父子关系的方式将电影彼此关联起来。除了外键(tmdb_id、推荐的_tmdb_id)之外,表中实际上不需要任何其他内容,因为您当前在其中的值(title、avg rating)是存储在tmdb_movies表中的非规范化值

现在想想未来,当你有数千部电影时,每部电影都可能有10部与之相关的推荐电影。对于任何一部电影,重复相同标题和不变的平均值的数据库存储都将浪费兆字节。更糟糕的是,平均值只是时间的快照。每当需要重新计算平均评级时,而不是更新tmdb_movie表中一行中的单个值,您现在必须更新推荐中的每一行,其中该电影被推荐为原始电影。这些是去正常化的一些成本

现在来看看分组的细节

首先,为了说明分组方式的工作方式,我建议您在SQLFIDLE或live db中运行以下查询:

SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average
FROM tmdb_movies 
LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id
GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title
Where tmdb_movies.tmdb_id=1
与您所做的不同的关键是,我删除了无用的GROUP_CONCAT语句,并在tmdb_movies.tmdb_id、recommendations.recommendations_title上创建了一个GROUP BY

理想情况下,这将是由id的,但我涵盖了上述内容,所以现在我们只能使用标题

正如您所看到的,您可以为每一部电影和推荐电影的独特组合获得一个组。看来这就是你想要的。请注意,我根本没有使用GROUP_CONCAT,您可以得到平均值和标题,每行一个

现在让我们假设您也想加入到cast表

我们再加上:

SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average
FROM tmdb_movies 
LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id
LEFT JOIN cast ON cast.recommendations_title=recommendations.recommendations_title
GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title
请注意,没有任何变化。您不会得到无关的行,因为GROUP BY已经减少了重复,并在每个组中保留一行,即使我们现在正在加入电影->推荐->演员阵容

所以,现在我假设您希望在结果中的一列中强制转换。以下是GROUP_CONCAT的实际用途和适用性:

SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average, GROUP_CONCAT(cast.name)
FROM tmdb_movies 
LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id
LEFT JOIN cast ON cast.recommendations_title=recommendations.recommendations_title
GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title

这里是:

尝试切换您的加入,因为这会将左表与右表进行比较:
tmdb_电影上的左加入演员阵容。tmdb_id=cast.cast_tmdb_id
不,它不起作用@aynberWhy你为什么要加入演员阵容,而演员阵容不是你要返回的?你为什么要用小组讨论来解决你不应该做的事情?GROUP_CONCAT是指当您有一个联接表,并且希望在一列中返回该联接的所有值(即标记、颜色等的列表)时,在您的情况下,可能cast将是您希望对_CONCAT进行分组的位置。您拥有GROUP_CONCAT on(title,vote_average)的列不应该是GROUP_CONCAT()。为了简单起见,我没有包括它。这里的所有行在我的原始代码@gviewWhy中都有一些用处。为什么推荐电影的id没有tmdb_id?制作一个新的SqlFIDLE,其中包含带有一些示例数据的cast表。我不能使用DISTINCT,因为有些值是相同的,而且非常好。我需要左join我不能使用DISTINCT是什么意思,因为有些值是相同的。。左连接在cast上有什么用处。。。你的预期结果与你的实际结果似乎正好相反,2部电影的评级为
7.5
,因此我如何使用DISTINCT?但这两部电影的名称不同。。所以不同的返回2行..@toby你小提琴的问题是你没有
SELECT tmdb_movies.movie_title, recommendations.recommendations_title, recommendations.recommendations_vote_average, GROUP_CONCAT(cast.name)
FROM tmdb_movies 
LEFT JOIN recommendations ON recommendations.recommendations_tmdb_id=tmdb_movies.tmdb_id
LEFT JOIN cast ON cast.recommendations_title=recommendations.recommendations_title
GROUP BY tmdb_movies.tmdb_id, recommendations.recommendations_title