Scusate ma è tutto il giorno che provo, qualcuno potrebbe consigliarmi qual è il modo più veloce per recuperare dei dati organizzati come segue:

codice:
tbl_contact   |  tbl_indirizzi   |  tbl_numeri     |  tbl_category
              |                  |                 |
id            |  value           |  value          |  id
nome          |  contact_id      |  contact_id     |  label
cognome       |  category_id     |  category_id    |  type
altro
In poche parole ho una lista di contatti in cui ogni contatto ha dei definiti nella tabella (nome cognome etc) ed altri dati che possono essere multipli memorizzati in alcune tabelle esterne:

un contatto può avere molti indirizzi o molti numeri, la cui associazione col contatto è data dalla foreign_key contact_id. Allo stesso modo un indirizzo/numero ha una categoria di appartenenza (casa, ufficio, cell) definita in un'altra tabella, legata al dato tramite una seconda foreign_key chiamata category_id.

Ora devo fare una lista dei contatti e mostrare tutti i dati legati ad esso quanti che siano.
L'idea è quella di creare una tabella in questo modo:

codice:
contatti.id   contatti.nome    datomultiplo.value   datomultiplo.label   datomultiplo.type

1             Paolo            Via Garibaldi        Casa                 Indirizzo
1             Paolo            Via Grandi           Ufficio              Indirizzo
1             Paolo            02020202             Casa                 Numero
2             Maria            Via Volta            Vacanze              Indirizzo
2             Maria            Via Roma             Ufficio              Indirizzo
2             Maria            32323232             Cell                 Numero
Le prime due colonne sono i dati della colonna "contact", la terza lista tutti i parametri di "indirizzi" o "numeri" che hanno contact_id = contact.id e dalla terza sono i dati della tabella categorie legati al rispetti indirizzo da category_id.
Una volta presa la tabella la pulisco in php (elimino i dati duplicati) per passarla allo script che renderizza la tabella.

Per farlo d'apprima ho pensato di usare più query da PHP ovvero:
1 - mi prendo tutti i contatti che devo far stare nella pagina
2 - ciclo il result set e faccio una query che mi recupera solo i dati del relativo id della riga

codice:
SELECT id, nome, cognome FROM contacts LIMIT 0, 20
e fin qui ok. Ma come metto insieme tutti i dati esterni organizzati come le ultime 3 colonne?
Primo dubbio sulla reale performance della query.

codice:
 SELECT value, contact_id, label, model
  FROM contacts, indirizzi
   LEFT JOIN categories 
   ON category_id = categories.id
  WHERE indirizzi.contact_id = 2
UNION
 SELECT value, contact_id, label, model
  FROM contacts, numeri
   LEFT JOIN categories 
   ON category_id = categories.id
  WHERE numeri.contact_id = 2
Così mi ritorna una tabella simile a quella mostrata sopra, ma senza tutti i dati duplicati del contatto E PER UN SOLO contatto. Ciclo in PHP e riorganizzo l'array.

Secondo dubbio: l'UNION è realmente l'unico metodo?
Terzo dubbio: per elencare 20 contatti devo eseguire 21 query consecutive. Non sarà forse un po' esagerato? Figuriamoci se nella pagina devo mostrarne 100.

Quindi ho optato per una query unica che mi ritornasse una tabella come quella sopra descritta.
Il problema è che probabilmente ho complicato tutto e combino un casino che è meglio farlo in Nmila richieste:

codice:
SELECT contact.id, contact.nome, contact.cognome, ext.value, ext.label, ext.model
FROM contact, (
  SELECT value, contact_id, label, model
    FROM indirizzi
     LEFT JOIN categories 
     ON category_id = categories.id
  UNION
   SELECT value, contact_id, label, model
    FROM numeri
     LEFT JOIN categories 
     ON category_id = categories.id
  ) AS ext
  WHERE contact.id = ext.id
  LIMIT 0,20
  ORDER BY nome ASC
Così uso una subquery che mi tira fuori una tabella con tutti i dati esterni "normalizzati" e io posso prendere solo i primi 20 e volendo aumentare la clause WHERE assottigliando il result set.
Ok, dite... e allora? Ecco:

1 - ci sono ancora le UNION che mi puzzano.
2 - Io sto cercando solo i primi 20 contatti. Per creare la tabella virtuale con la subquery io mi smazzo tutta li lista degli indirizzi e dei numeri. Se ho registrato 1000 contatti ed ho 2 indirizzi a persona sono 2000 indirizzi... e me ne servono solo i primi 20. Non posso usare LIMIT, limiterei il result set della subquery, così se il primo contatto ha 20 indirizzi, non mi tira fuori i successivi.

Ordunque... che si fa? Così funziona... ma sicuramente è meglio il primo approccio.
Mi sarò perso in un bicchier d'acqua? Qualcuno potrebbe risolvermi qualche dubbio?
Come fareste voi?

Per ora sto usando il primo metodo ma vorrei chiarirmi le idee
Grazie mille
Ciao
Yuri