使用PHP中的group_concat回显mysql数据

时间:2017-07-05 16:50:27

标签: php mysql

这是我的SQL小提琴:SQL Fiddle

我试图用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>';
    }
}

<小时/> 输出此代码:

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Batman Begins- 7.5

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Captain America: The First Avenger- 6.6

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Inception- 8

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man- 7.3

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

Iron Man 2- 6.6

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Dark Knight Rises- 7.5

The Lord of th- 8

但如果我删除此行LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_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

2 个答案:

答案 0 :(得分:0)

使用LEFT JOIN cast
对于选择值是不可用的(结果是选择ayway,因为它们基于maun table movie_title 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

或者更好地使用left join pn cast

   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

答案 1 :(得分:0)

您帖子中的许多内容都没有加起来。你的sql小提琴完全错过了演员表。我已经评论过您正在使用GROUP_CONCAT。您的问题没有完整的信息来帮助我们了解您的问题。

话虽如此,我相信我已经推测出了你真正想要的东西。主要问题是您的GROUP BY应包括原始电影和推荐电影。这将为每组电影/推荐组合返回一行。您可以使用GROUP_CONCAT在一列中获取强制转换。此外,我认为你想要的演员数据实际上是推荐电影的演员阵容,而不是原始电影的演员阵容。您可以将两者结合在一起,但在此查询的上下文中,在我看来,您希望将推荐影片的强制转换组合到GROUP_CONCAT的一列中。正如我对您所评论的那样,问题是您在推荐表中没有推荐的电影的tmdb_id。坦率地说,这是一个非规范化的结构(存储标题而不是id),并且在关系上是错误的,浪费的并且可能令人困惑。

为什么会这样?

首先,推荐表没有主键,需要一个。标题也不是一个好的候选键,因为有许多电影具有相同的标题。使用您的系统,无法确定哪些电影可能具有相同的标题。因此,您应该拥有的是tmdb_id作为外键,此时,您不需要(也不想要)标题,因为它可以从tmdb_movies表中获取。您的推荐表基本上是一个多对多表,它以父对子的方式将电影相互关联。除了外键(tmdb_id,recommended_tmdb_id)之外,实际上不需要在表中包含任何其他内容,因为您当前拥有的值(标题,平均等级)是存储在tmdb_movies表中的非规范化值。

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

现在来看GROUPing的细节。

首先说明GROUP BY的工作方式,我建议你在sqlfiddle或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,但我在上面介绍过,所以现在我们必须使用标题。

正如您所看到的,每个独特的Movie&amp;组合都会获得一个GROUP。推荐电影。看来这就是你想要的。请注意,我根本没有使用GROUP_CONCAT,而是获得平均值和标题,每行一个。

现在让我们假设您也想加入演员表。

我们将其添加到:

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已经减少了重复并且每组留下一行,即使我们现在加入了movie-&gt; recommended-&gt; cast

所以,现在我假设您希望在结果中的一列中使用强制转换。这里是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

此处the sqlfiddle to this