The easiest way is probably to pull the list of categories, iterate through and pull their attached products. (I.e. several queries.)
For instance (pseudocode):
$result = fetch_assoc("SELECT category_id FROM categories");
foreach($result as $row)
{
echo $row['category_id'];
$result2 = fetch_assoc("SELECT product_id FROM products");
foreach($result2 as $row2)
{
echo $row2['product_id'];
}
}
If you want to do it all in one query you can do something like:
$result = fetch_assoc("SELECT product_id, category_id FROM products p JOIN categories c ON p.category_id = c.category_id ORDER BY c.category_id ASC");
$last = null;
foreach($result as $row)
{
# Output the category whenever it changes
if($row['category_id'] != last)
{
echo $row['category_id'];
$last = $row['category_id'];
}
echo $row['item_id'];
}
Then you can iterate over the result set and pull out the category name whenever it changes.
There may be a more sophisticated, elegant way to write the SQL to do everything before you get it from the database, but I'm not that smart. ;)
Note: Examples use pseudo code. I use a mysql abstraction class that works like:
$db->query("SELECT stuff");
$db->multi_result(); // returns 2d-associative array
I can then foreach($db->multi_result() as $row)
, which is super lazy and awesome.
I can post the code for the abstraction layer if you like.