You are correct in that it retrieves one row per photo. But since each row of photo data is retrieved together with data from its corresponding gallery, you allready have both gallery and photo data in each row.
For example, dealing with this in PHP by iterating over the result set just once
# ORDER BY very important for this to work
$result = $db->query(
'SELECT gallery.id AS gallery_id, photo related stuff, ...
FROM ...
JOINS ...
ORDER BY gallery_id
');
$last_gallery = false;
while ($row = $result->fetch())
{
# if the current photo's gallery ($row['gallery_id']) is not the same as the
# last photo's gallery ($last_gallery), output a new header (or new table row or
# whatever way you use to group things
if ($last_gallery != $row['gallery_id'])
{
# additionally, if $last_gallery !== false, this isn't the first iteration
# and we have to close div, table row or some such from before
if ($last_gallery !== false)
echo '</div>';
echo '<h3>'.$row['gallery_name'].'</h3>';
$last_gallery = $row['gallery_id'];
}
echo '<img src="'.$row['photo_url'].'" alt="" width="'.$row['w'].'" height="'.$row['h'].'" />';
}
You can choose to either use aggregate functions and group by clause to create one row per gallery, or create your gallery array containing photo arrays in PHP.
Doing it in PHP but iterating over the result set twice, thus being less efficient than the above.
# ORDER BY gallery_id is not needed for this approach
$result = $db->query(
'SELECT gallery.id AS gallery_id, photo related stuff, ...
FROM ...
JOINS ...
');
$galleries = array();
while ($row = $result->fetch())
{
# $galleries will be an array of gallery arrays, indexed by gallery id
$galleries[$row['id']][] = $row;
}
foreach ($galleries as $gallery_id => $photo)
{
# in reality, each $photo obviously contain all gallery data as well,
# such as gallery id ($photo['gallery_id'] is the same as $gallery_id here)
echo 'gallery name etc';
foreach ($photo as $p)
{
echo 'img element etc';
}
}
And doing it directly in your SQL query
SELECT gallery.id AS gallery_id, gallery.name as gallery_name, GROUP_CONCAT(photo_url SEPARATOR ', ') AS photos
FROM ...
JOINS
GROUP BY gallery_id, gallery_name
But, I'm curious as to why you want to avoid having one row per photo? How else will you display each separate photo in a gallery? Or are you going to explode your comma separated string of photos into an array? If so, then you are doing double work, first having the DB concatenate these values into one string, and then having your PHP scritp undo this work by exploding it back into an array.