简体   繁体   English

在PHP中使用group_concat回显mysql数据

[英]Echo mysql data using group_concat in PHP

This is my SQL Fiddle: SQL Fiddle 这是我的SQL提琴: SQL提琴

I am trying to echo this result using PHP. 我正在尝试使用PHP回应此结果。 This is my expected result: 这是我的预期结果:

// 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

My PHP Code: 我的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>';
    }
}


Output of this code: 此代码的输出:

 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 

But If i remove this line LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id then, my php code works fine. 但是,如果我删除此行,然后LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id进行LEFT JOIN cast ON cast.cast_tmdb_id=tmdb_movies.tmdb_id ,则我的php代码可以正常工作。

Expected Result: 预期结果:

 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 

The use of the LEFT JOIN cast LEFT JOIN cast
is unuseful for the select values (the results are select ayway because are based on maun table movie_title adn don't return useful info because there are no columns from di table in select clause ) and produce a resulting set with more rows 对选择值无用(由于基于maun表movie_title的结果是select ayway,并且因为select子句中di table中没有列,所以不返回有用的信息),并产生具有更多行的结果集

so if you want insist on thi left join you can add DISTINCT to your originale query 因此,如果您想坚持左联接,可以将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

or better don use left join pn cast 或最好不要使用左连接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

Many of the things you have in your post don't add up. 您帖子中的许多内容都没有加在一起。 Your sql fiddle is missing the cast table entirely. 您的sql小提琴完全缺少转换表。 I have already commented that you are using GROUP_CONCAT inappropriately. 我已经评论说您不恰当地使用了GROUP_CONCAT。 Your question does not have the complete information to help us understand your problem. 您的问题没有完整的信息来帮助我们理解您的问题。

With that said, I believe I have surmised something close to what you actually want. 话虽如此,我相信我已经推测出一些接近您真正想要的东西。 The main problem is that your GROUP BY should include both the original movie AND the recommended movies. 主要问题是您的GROUP BY应该同时包含原始电影和推荐电影。 This will return you one row per group combination of movie/recommendation. 每组电影/推荐组合将为您返回一行。 You can use GROUP_CONCAT to get the cast in one column. 您可以使用GROUP_CONCAT在一列中获取演员表。 Furthermore, I think that the cast data you want is actually the cast of the recommended movie, not the cast for the original movie. 此外,我认为您想要的演员表数据实际上是推荐电影的演员表,而不是原始电影的演员表。 You could get both together, but in the context of this query, it seems to me that you would want the cast of the recommended movie assembled into one column with GROUP_CONCAT. 可以将两者放在一起,但是在此查询的上下文中,在我看来,您希望将推荐电影的演员表与GROUP_CONCAT组合为一列。 As I commented to you, the problem is that you don't have the recommended movie's tmdb_id in the recommendation table. 正如我向您评论的那样,问题在于您在推荐表中没有推荐电影的tmdb_id。 Quite frankly that is a denormalized structure (storing the title rather than the id) and is relationally incorrect, wasteful and potentially confusing. 坦率地说,这是一种非规范化的结构(存储标题而不是ID),并且关系不正确,浪费且可能造成混淆。

Why is this? 为什么是这样?

First off, the recommendation table has no Primary key and it needs one. 首先,推荐表没有主键,需要一个主键。 Title is not really a good candidate key either, because there are many movies that have the same title. 标题也不是一个很好的候选键,因为有很多电影具有相同的标题。 With your system there is no way to determine which film out of several that may have the same title. 对于您的系统,无法确定几部电影中可能具有相同标题的电影。 Thus what you should have, is the tmdb_id as a foreign key, and at that point, you would not need (nor want) the title, because it could be gotten from the tmdb_movies table. 因此,您应该拥有的是将tmdb_id作为外键,并且此时,您将不需要(也不需要)标题,因为可以从tmdb_movies表中获取它。 Your recommendation table is essentially a many-to-many table that relates movies to each other in a parent to child manner. 您的推荐表本质上是一个多对多表,该表以父子方式将电影彼此关联。 Aside from the foreign keys (tmdb_id, recommended_tmdb_id) there doesn't actually need to be anything else in the table, since the values you currently have in there (title, avg rating) are denormalized values that are stored in the tmdb_movies table. 除了外键(tmdb_id,recommended_tmdb_id)外,表中实际上不需要任何其他内容,因为您当前在那里的值(标题,avg等级)是存储在tmdb_movies表中的非规范化值。

Now think ahead to the future, when perhaps you have thousands of movies, each of which may have 10 recommended movies related to it. 现在考虑一下未来,也许您有成千上万部电影,每部电影可能都有10部与之相关的推荐电影。 You will be wasting for any one movie, megabytes of database storage repeating the same title and average value that doesn't change. 您将浪费任何一部电影,重复存储相同标题和平均值的百万字节数据库存储。 Worse yet, averages are a snapshot in time. 更糟糕的是,平均值只是时间的快照。 Whenever the average rating needs to be recalculated, rather than updating a single value in one row of the tmdb_movie table, you now have to update every single row in recommendation where that movie was recommended to the original. 每当需要重新计算平均收视率时,而不是更新tmdb_movie表的一行中的单个值时,现在您都必须更新建议中将电影推荐给原始电影的每一行。 These are some of the costs of de-normalization. 这些是非规范化的一些成本。

Now to the specifics of GROUPing. 现在到分组的细节。

First to illustrate the way that GROUP BY works, I suggest you run these queries in your sqlfiddle or live db: 首先说明GROUP BY的工作方式,建议您在sqlfiddle或实时数据库中运行以下查询:

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

The key thing that is different from what you've been doing, is that I removed the useless GROUP_CONCAT statements, and did a GROUP BY on tmdb_movies.tmdb_id, recommendations.recommendations_title. 与您所做的不同的关键是,我删除了无用的GROUP_CONCAT语句,并对tmdb_movies.tmdb_id,recommendations.recommendations_title进行了GROUP BY。

Ideally this would be by the id's but I covered that above, so for now we have to just use title. 理想情况下,这应该是id的,但是我已经在上面进行了介绍,所以现在我们只需要使用title。

As you can see, you get a GROUP for each unique combination of Movie & Recommended Movie. 如您所见,电影和推荐电影的每个唯一组合都会获得一个GROUP。 It appears this is what you want. 看来这就是您想要的。 Notice that I didn't used GROUP_CONCAT at all, and you get the average and the title, one per row. 请注意,我根本没有使用GROUP_CONCAT,您得到的是平均值和标题,每行一个。

Now let's assume you want to also join to the cast table. 现在,假设您还想加入转换表。

Let's add that in: 让我们添加到:

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

Notice that NOTHING CHANGES. 请注意,没有任何变化。 You do not get extraneous rows, because the GROUP BY already reduces duplicates and leaves one row per group, even though we are now joining movie->recommendation->cast 您不会得到多余的行,因为即使我们现在正在加入movie-> recommendation-> cast,GROUP BY已经减少了重复项,并且每组只留下一行

So, now I will assume you want the cast in one column in the result. 因此,现在我假设您希望将结果强制转换为一列。 Here is where GROUP_CONCAT actually comes in useful and seems appropriate: 这是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

Here's the sqlfiddle to this : 这是sqlfiddle

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

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