【问题标题】:PHP/MYSQL: how to loop matching results from a query already inside a while loopPHP / MYSQL:如何在while循环中循环来自查询的匹配结果
【发布时间】:2015-02-14 08:43:48
【问题描述】:

我对 PHP/MYSQL 很陌生,发现这很难解释,所以希望有人能理解我想要做什么。我有一个收集艺术家和歌曲信息的数据库。我希望能够将艺术家链接到歌曲并显示带有歌曲信息的“信用”。

我有一个数据库,其中包含类似这样的表:

艺术家 |艺术家 ID,艺术家姓名

学分 | credit_id, credit_name

歌曲 | song_id, song_name

Credit_To_Artist | credit_id、artist_id、song_id


示例数据:

艺术家 | 2、彼得马克

艺术家 | 5、梅特·克里斯蒂安森

学分 | 1、制片人

学分 | 2、作家

学分 | 3、主唱

歌曲 | 23、游戏

Credit_To_Artist | 1、2、23

Credit_To_Artist | 2、2、23

Credit_To_Artist | 3、5、23


我创建了一个页面“song.php”,显示每首歌曲的信息,使用 mysql_real_escape_string 从 URL 中获取歌曲 ID:

$id = mysql_real_escape_string($_GET['id']);

if (!$id) {
    die('Please provide an id!');
}

$query = "SELECT * FROM `Credit_To_Artist` AS c2a 
INNER JOIN `Credits` AS cr ON cr.credit_id = c2a.credit_id
LEFT OUTER JOIN `Artist` AS a ON a.artist_id = c2a.artist_id
LEFT OUTER JOIN `Song` AS s ON s.song_id = c2a.song_id
WHERE c2a.song_id = $id";

$res = mysql_query($query);

$row = mysql_fetch_assoc($res);

我遇到的问题是,我希望能够列出与该歌曲相关联的所有艺术家,以及他们在旁边括号中的所有作品。由于每首歌都有不止一位艺术家,而且他们中的大多数人都有不止一个功劳(制作人、作家、歌手等),我不知道如何编写一个循环函数来显示这两者。下面是我试图说明我的意思,尽管它显然不起作用:

 while ($row = mysql_fetch_array($res)) {
            $artist = $row[artist_name];

        echo "$artist";

        while ($row = mysql_fetch_array($res)) {
            $credit = $row[credit_name];
            echo "$credit";
            }
        echo "<br />";
    }

这是我希望从上面的示例数据中实现的理想目标:

歌曲:游戏

致谢: Peter Mark(制片人、作家) 梅特·克里斯蒂安森(歌手)

【问题讨论】:

  • 我认为您正在搜索GROUP_CONCAT(..)。或者,循环遍历所有结果并将它们添加到数组中,然后用逗号将它们内爆。
  • 谢谢你的回复,如果不是太麻烦你能给我一个简单的例子吗?作为新手,这些听起来像是很好的解决方案,但我可能需要几个月的时间来学习如何编写它们哈哈

标签: php mysql loops while-loop


【解决方案1】:

让我们从表格开始,这是我认为你应该做的事情

artist | id, name
song | id, title
credit | id, credit
song_artists | id, song_id, artist_id
credit_to_artists | id, song_artists_id, credit_id

应该是处理你想要的那种关系的方式。

这里是 PHP 代码,它可能不是最有效的,但它会完成这项工作

$query = "SELECT * FROM song_artists WHERE song_id = $id_from_link";
$result = mysql_query($query);

while($row = mysql_fetch_array($result))
{
  $artistQuery = "SELECT * from artist WHERE id = {$row['artist_id']}";
  $artistResult = mysql_query($artistQuery);
  while($artistRow = mysql_fetch_array($artistResult))
  {
    echo "The Artist: " . $artistRow['name'];
  }

  echo $songArtistId;
  $creditToArtistQuery = "SELECT * FROM credit_to_artists WHERE song_artists_id = {$row['id']}";
  $creditToArtistResult = mysql_query($creditToArtistQuery);
  if(mysql_num_rows($creditToArtistResult)>0)
  {
    echo " { ";
    $isFirstCredit = true;

    while($creditToArtistRow = mysql_fetch_array($creditToArtistResult))
    {
      $creditQuery = "SELECT * FROM credit WHERE id = {$creditToArtistRow['credit_id']}";
      $creditResult = mysql_query($creditQuery);
      while($creditRow = mysql_fetch_array($creditResult))
      {
        if($isFirstCredit)
        {
         echo $creditRow['credit'];
         $isFirstCredit = false;
        }
        else
        {
          echo ", " .$creditRow['credit'];
        }
      }
    }
    echo " } <br />";
  }


}

【讨论】:

    【解决方案2】:

    你有两个选择:

    GROUP_CONCAT(..)

    您可以使用GROUP_CONCAT(..)。此 mysql 函数将每个组中的列中的值分组。在这种情况下,您可以将 sql 更改为按艺术家 ID 分组。

    SELECT a.artist_name as aname, GROUP_CONCAT(c.credit_name) as credits
    FROM Credits_To_Artist as c2a
    JOIN Artist as a ON c2a.artist_id = a.artist_id
    JOIN Credits as c ON c2a.credit_id = c.credit_id
    GROUP BY c2a.credit_id
    

    你的行看起来像:

    Array( "aname" => "name",
           "credits" => "function 1,function 2" )
    

    GROUP_CONCAT 最大的问题是如果你必须将很多值连接在一起,它可能会超过行的最大宽度。您的问题似乎并非如此。这种方法不需要循环。

    添加到数组

    如果您保持查询原样,则每个“信用”都有一行。您可以通过将数据添加到数组来准备数据,然后在 php 中使用 implode(..) 添加逗号。

    $artists = Array();
    while( $row = mysql_fetch_array($res) ) {
        $artist = $row[artist_name];
        $credit = $row[credit_name];
    
        if( !array_key_exists( $artist, $artists ) ) {
            $artists[$artist] = Array();
        }
    
        $artists[$artist][] = $credit;
    }
    
    foreach( $artists as $artist => $creditarr ) {
        $credits = implode( ", ", $creditarr );
        echo "{$artist} ({$credits})<br>";
    }
    

    您会发现,在数组中准备数据有时比编写执行相同操作的查询要快得多。我可能会选择后一种解决方案。

    【讨论】:

    • “添加到数组”解决方案完美运行,非常感谢!
    • 另外,我敢肯定这很简单,但我怎样才能使“{$artist}”成为在其 URL 中使用艺术家 ID 的链接? (例如 {$artist}
    • 创建一个数组$artisttoid。确定每个艺术家只运行一次的代码,并将您的翻译添加到那里的数组中。然后你可以做$artisttoid[$artist]
    • 我不太懂数组,但我会试试,谢谢
    • 我不想成为一个唠叨的人,但我一直在努力,但我无法用新数组更改代码,你能帮忙或提供更详细的说明吗?
    猜你喜欢
    • 2013-03-11
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 2023-03-30
    • 2019-08-05
    • 1970-01-01
    • 2012-09-05
    • 1970-01-01
    相关资源
    最近更新 更多