我正在尝试在网页上正确显示MySQL查询。
我有4个连接在一起的简单表格
singers
:singer_id
,singer_name
songs
:singer_id
,song_name
,album_id
albums
:singer_id
,album_id
,album_name
我已经设法使用此查询获取这些表。
SELECT singers.singer_name, songs.song_name, albums.album_name
FROM singers
LEFT JOIN songs ON singers.singer_id = songs.singer_id
LEFT JOIN albums ON albums.album_id = songs.album_id
WHERE singers.singer_id = ?
ORDER BY songs.song_id DESC
我现在遇到的问题是我似乎无法正确显示这些表格。
假设我有一个拥有1张专辑和11首歌曲的歌手。 这是我为这位歌手所得到的结果。
singer_name | song_name | album_name
__________________________________________________
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
singer name | song name | album name
所以我没有获得1张专辑,而是获得了11次相同的专辑。
网页上的我正在使用foreach()
显示相册
而且我得到的是同一张专辑而不是一张专辑。
现在提出问题......
如何才能展示专辑3次?
(没有硬编码,因为我可能还有一个有9张专辑的歌手)。
提前感谢您的帮助。
编辑:
这是我显示歌曲的方式
<?php foreach($results as $song): ?>
<tr>
<td></td>
<td>
<a href="/song/<?php echo urlencode($song['song_url']); ?>/" class="song">
<span><?php echo $song['song_name']; ?></span>
</a>
</td>
<td>
<a href="/album/<?php echo urlencode($song['album_name']); ?>/" class="album">
<?php echo $song['album_name']; ?>
</a>
</td>
<td>
<span class="time">
<?php echo $song['song_time']; ?>
</span>
</td>
<td>
<a href="/search/?search=<?php echo urlencode($song['song_genre']); ?>" class="genre">
<?php echo $song['song_genre']; ?>
</a>
</td>
<td><a href="#" class="play">נגן</a></td>
</tr>
<?php endforeach; ?>
即使歌曲没有附加到任何专辑,我也能收到所有歌曲。正是我想要的。
显示相册的问题:
<?php foreach($results as $album): ?>
<li>
<a href="/album/<?php echo urlencode($album['url']); ?>/" class="album">
<img src="/media/<?php echo $album['singer_dir'] . '/' . $album['album_thumb']; ?>" alt="" />
<span class="album_name"><?php echo $album['album_name']; ?></span>
</a>
</li>
<?php endforeach; ?>
这位歌手有1张专辑,但我得了11张。因为这张专辑有11首歌曲。
我只需要显示一次......
答案 0 :(得分:2)
在不了解$ result变量的情况下(例如,它可能是PDO对象或数组,我不知道)我的回答必须是一个hackish:
<?php foreach($results as $album): ?>
<li>
<a href="/album/<?php echo urlencode($album['url']); ?>/" class="album">
<img src="/media/<?php echo $album['singer_dir'] . '/' . $album['album_thumb']; ?>" alt="" />
<span class="album_name"><?php echo $album['album_name']; ?></span>
</a>
</li>
<?php break; ?>
<?php endforeach; ?>
就我个人而言,我不会在我自己的代码中这样做,但如果没有更多的代码图片和更清楚地了解你想要做什么,那就是它。
编辑1:
如果是这种情况,那么您需要的只是以下内容。 foreach是不必要的:
<li>
<a href="/album/<?php echo urlencode($result[0]['url']); ?>/" class="album">
<img src="/media/<?php echo $result[0]['singer_dir'] . '/' . $result[0]['album_thumb']; ?>" alt="" />
<span class="album_name"><?php echo $result[0]['album_name']; ?></span>
</a>
</li>
编辑2:
SELECT album_name
FROM albums
WHERE singer_id = ?
使用foreach循环遍历此结果集。
答案 1 :(得分:1)
LEFT OUTER JOIN方法按照您的设计设计,相册应该由于笛卡尔积而重复。
不清楚你的观点,我用两种方式解释你的问题。 重复歌手,重复歌曲,重复专辑,因为没有分组。 2.非重复的歌手/歌曲,只想分组专辑。
如果你的意思是1,答案很简单。添加不同的关键字 我确定你的意思是2,你应该管理重复信息。并且,如果您使用html表格输出, rowspan 属性将为您提供帮助。
示例数据:
CREATE TABLE t
( a varchar(25)
, b varchar(25)
, c_id integer
, c varchar(25)
);
INSERT INTO t VALUES ( '2ne1', 's1', 1, 'lonely');
INSERT INTO t VALUES ( '2ne1', 's2', 1, 'lonely');
INSERT INTO t VALUES ( '2ne1', 's3', 1, 'lonely');
INSERT INTO t VALUES ( '2ne1', 's4', 1, 'lonely');
INSERT INTO t VALUES ( '2ne1', 's5', 1, 'lonely');
INSERT INTO t VALUES ( 'anonymous', 'rock1', 2, 'um album');
INSERT INTO t VALUES ( 'anonymous', 'rock2', 2, 'um album');
INSERT INTO t VALUES ( 'anonymous', 'rock3', 2, 'um album');
示例代码:
<?php
$conn = mysql_connect('localhost', '..', ',,')
OR die (mysql_error());
mysql_select_db('test')
OR die (mysql_error());
$rs = mysql_query
( 'select t.a, t.b, r.span, t.c_id, t.c '.
'from t '.
'join '.
'( select c_id, count(c) span '.
' from t '.
' group by c_id) r '.
' on t.c_id = r.c_id ' )
OR die (mysql_error());
echo "<html><table border=1>\n";
$old_c_id = -1;
while ($row = mysql_fetch_array($rs, MYSQL_ASSOC)) {
echo "<tr>";
echo "<td>".htmlspecialchars($row['a'])."</td>\n";
echo "<td>".htmlspecialchars($row['b'])."</td>\n";
if ($old_c_id != $row['c_id'])
{
$old_c_id = $row['c_id'];
echo sprintf("<td rowspan=%d>", $row['span'])
. htmlspecialchars($row['c'])
. "</td>\n";
}
echo "</tr>\n";
}
echo "</table></html>";
?>
答案 2 :(得分:1)
请参阅我对how to display the changing values only问题的回答 - 我在previous question的评论中提到了这一点。它基本上归结为在不拆分SQL查询的情况下将结果分组到PHP中。
首先,query your database使用以下查询:
SELECT a.artist_name, COALESCE(b.album_name, '(no album)'), s.song_name,
FROM songs s
LEFT JOIN artists a
ON s.singer_id = a.singer_id
LEFT JOIN albums b
ON s.album_id = b.album_id AND s.singer_id = b.singer_id
ORDER BY a.artist_name, b.album_id, s.song_id # order by artist, album then song
这将为您提供一个结果集,其中每一行代表完整的歌曲(包括艺术家和专辑名称) - 想象一下电子表格 - 这就是您要求的加入到第一位。我们只输出一次这个表,打印艺术家和专辑一次(正确的ORDER BY
对此非常重要。
$prev = array( 'artist' => null, 'album' => null );
while(($row = mysqli_fetch_assoc($result)) !== FALSE) {
// print groupings
if($row['artist_name'] != $prev['artist'])
displayArtist(); // only display the first occurrence of each artist
if($row['album_name'] != $prev['album'])
displayAlbum($row['album_name']); // same goes for albums
displaySong($row['song_name']); // but display every song
$prev['artist'] = $row['artist_name'];
$prev['album'] = $row['album_name'];
}
format*()
可以简单如下:
function displayArtist($artist_name) {
printf('<h1 class="artist">%s</h1>', htmlspecialchars($artist_name));
}
function displayAlbum($album_name) {
printf('<h1 class="album">%s</h1>', htmlspecialchars($album_name));
}
function displaySong($song_name) {
printf('<div class="song">%s</div>', htmlspecialchars($song_name));
}
但你当然可以像问题一样使用表格布局