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