views:

132

answers:

1

I have the following tables in mysql:

team: id, name, [more stuff]
person: id, name, team, [more stuff]
entry: id, name, team, [more stuff]
registrations: id, event_id, team, status
registration_people: registration_id, person_id
registration_entries: registration_id, entry_id

I would like to query the database and return details about each person and entry, grouped by registration. I've learned over the years to do as much as I can in SQL, however, I don't see a good way to generate this in a single query without doing a lot of work in PHP. The naive way to do this would be [pseudocode]:

$registrations = $model->get_registrations($event_id);
foreach ($registrations as $registration)
{
    $registration['people'] = $model->get_people_in_registration($registration['id']);
    $registration['entries'] = $model->get_entries_in_registration($registration['id']);
}
return $registrations;

However, this code does many round-trips to the server, and shouldn't be used. The other idea I had was to do something like:

$registrations = $model->get_registrations($event_id);
$registration_entries = $model->get_registration_entries($event_id);
$registration_people = $model->get_registration_people($event_id);
foreach ($registrations as $r)
    $reg[$r['id']] = $r;
foreach ($registrations_entries as $e)
    $reg[$e['registration_id']]['entries'][] = $e;
foreach ($registrations_people as $p)
    $reg[$p['registration_id']]['people'][] = $p;
return $reg;

where get_registration_entries/get_registration_people do a join and grab all registration_entries that are associated with the registrations in $event_id. However, this seems like I'm doing a join in PHP, when I might be able to get SQL to do it for me. Am I just being paranoid, or am I missing something here?

+2  A: 

The "do as much in SQL as possible" concept is only valid when it decreases amount of data read from the database or the number of roundtrips to the database. If you need to get the data anyway, what's the point of grouping it in the database? It is much easier to do in PHP.

You should do something like this:

select r.registration_id, p.*
from registration_people rp, registrations r, person p
where /* your filter conditions on the "registration" table */
and rp.registration_id = r.id
and p.id = rp.person_id

(I guess this is pretty much the same as your second approach)

This way, you get all the relevant data from the database, and no more. Now you can group the results locally in PHP. This approach is quite efficient as you only get as much data from the database as you need and you don't make unnecessary roundtrips to the database.

DrJokepu
Well, at my first job there was a lot of code on the web-server side that did things like sorting and (simple) joining that was much better done on the DB side, as well as code that made lots of round trips. It's made me paranoid I guess.
FryGuy
FryGuy: I agree, sorting, joining, stuff like that are usually to be done at server side. In this case though, you can't really group the rows on the database side: of course you can ask for multiple result sets but that's kind of pointless.
DrJokepu