Hi,
The way you describe is probably the best way to do it in general.
I'll give an example - there is table A, which has fields id and frog, and table B, which has fields id, aid (foreign key to the id field in A), and zombie. You can have between 0 - N B entries for each A.
1. Simple way (1 query)
SELECT
A.id, A.frog, B.zombie
FROM
A
LEFT JOIN B ON B.aid = A.id
Then loop through results in PHP - each time A.id changes, start a new object, otherwise add the 'zombie' field to an array in the existing object.
2. Complex way (2 queries)
SELECT A.id, A.frog FROM A;
SELECT B.aid, B.zombie FROM B;
Then loop through results of the second query in php - for each one, add the resulting zombie to an array in the object you already have for a.
The complex approach is slightly more elegant and is better if there is a significant quantity of data in the fields of A that you are retrieving (i.e. if it that 'frog' field in my example was large) since you will retrieve those multiple times, unnecessarily.
The simple approach is uglier but can perform better in certain cases because there is only a single query, particularly if both queries have to do a complicated set of conditions and more joins in order to find out which rows of A and B to include.
Looping through all the results of A and calling a separate query each time to get the corresponding Bs would be a third option, but as you already noted that one is unacceptable in performance terms (especially when the alternatives are not that complicated) unless you are certain that the number of entries returned from your query for A is bounded (ie can never be greater than, say, 3 or something).
--sam