2013-08-19 9 views
6

Al momento ho un problema di SQL e PHP in cui io uso questa dichiarazione per ottenere tutto, dai servizi, così come le sue tabelle associate:MySQL Comma Separated Values ​​

$db = $this->getDbo(); 
$query = $db->getQuery(true); 

// Select the required fields from the table. 
$query->select(
     $this->getState(
       'list.select', 'a.*' 
     ) 
); 

$query->from('`#__services_service` AS a'); 
$query->where("a.zone"); 

$query->select('zone.name AS zone, zone.description AS zone_description, zone.price AS zone_price, zone.interval_recommended AS interval_recommended'); 
$query->join('LEFT', '#__services_zones AS zone ON zone.id = a.zone'); 

$query->select('category.icon AS category'); 
$query->join('LEFT', '#__services_categories AS category ON category.id = a.category'); 

Ma nella tabella di zona mi unisco, ci sono virgole valori separati '1,2' e dopo aver creato un array associativo dove raggruppo i servizi alle loro zone un servizio singolare va solo a una zona singolare, invece di quando il valore nella tabella è '1,2' dovrebbe essere in entrambi zone ... ho la sensazione che sia a causa della 'zone.name AS zone', perché poi restituisce solo un nome e se lo dico 'zone AS zone' che tornare da virgola numeri separati ...

Qui è come ordinare l'array:

foreach($this->items as $item){ 
if(!isset($zones[ $item->zone ])) 
$zone_items[ $item->zone] = array(); 
$zone_items[ $item->zone ][] = $item; 

    $zones[$item->zone] = array(
     'zone' => $item->zone, 
     'zone_interval' => $item->interval_recommended, 
     'zone_description' => $item->zone_description, 
     'zone_price' => $item->zone_price, 
     'items' => $zone_items[$item->zone] 
    ); 

} 

e visualizzarla:

<?php foreach($zones as $zone): ?> 
    <div class="row-fluid zones-page"> 
     <div class="row-fluid zone-title-block"> 
      <div class="span4 zone-name"><h1><?php echo $zone['zone']; ?></h1></div> 
      <div class="span7 zone-description"> 
       <?php echo $zone['zone_description']; ?> 
       <?php if($zone['zone_interval'] == 1): ?> 
        <span class="interval pull-right">Interval Recommended</span> 
       <?php endif; ?> 
      </div> 
     </div> 

     <?php foreach($zone['items'] as $items) :?> 
     <div class="row-fluid zone-services-contain"> 
      <div class="span1"><div class="zone-icon"><?php //echo $items->category; ?></div></div> 
      <div class="span11 zone-services"> 
       <h4><?php echo $items->name; ?></h4> 
       <div><?php echo $items->description; ?></div> 
      </div> 
     </div> 
     <?php endforeach; ?> 

     <div class="row-fluid zone-amount"> 
      only <div><?php echo 'R' . $zone['zone_price']; ?></div> 
     </div> 
    </div> 
    <div class="bicycle-divider"> 
     <div class="bicycle-icon"></div> 
    </div> 
<?php endforeach; ?> 

Qualsiasi aiuto è molto apprezzato.

La tabella Services assomiglia:

enter image description here

E il Zones Tabella:

enter image description here

+0

Che aspetto ha la tabella? –

+0

quale? ... i servizi, le zone o le categorie? –

+0

La tabella delle zone. –

risposta

8

Questo è il motivo per cui la gente di solito usano tabelle di collegamento a che fare con molti-a-molti come questo. Un servizio può avere più zone, una zona può avere più servizi. Interrogare un campo separato da virgole e usarlo in un join con un altro tavolo è piuttosto difficile.

avete due opzioni, una delle quali si tratta di fare nel modo giusto, e si permette di mantenere il modello di database corrente. Vi suggerisco caldamente di farlo nel modo giusto, ma per rispondere alla vostra domanda entrerò prima nell'altra opzione.

Separate semplicemente le vostre domande. Basta avere il campo separato da virgole nella query principale, quindi eseguire una seconda query per ottenere i nomi delle zone:

SELECT * FROM zone WHERE id IN ($zoneIdsYouSelected) 

Ora, se si sta lavorando con un profilo, questo probabilmente non è molto performante, perché si vuol dire Dovrò eseguire una query per la lista e un'altra per ogni riga. Un'alternativa sarebbe quella di ottenere tutte le zone in una matrice e quindi selezionare da quella utilizzando PHP in base allo $zoneIdsYouSelected. In questo modo puoi farla franca con 2 query invece se quella che avevi intenzione di realizzare, al contrario di una query per riga di dati.

Il modo corretto consiste nel creare una tabella di collegamenti che contiene semplicemente due campi: zone_id e service_id. Se poi si esegue una query come questa, si otterrà tutti i nomi in un "campo" nel set di risultati:

SELECT s.id, s.name, s.description, s.price, s.category, s.ordering, 
     s.state, s.checked_out, s.checked_out_time, s.created_by, 
     GROUP_CONCAT(DISTINCT z.name ORDER BY z.name ASC SEPARATOR ', ') AS zones 
FROM  service s JOIN service_zone sz ON s.id = sz.service_id 
     JOIN zone z ON z.id = sz.zone_id 
GROUP BY s.id, s.name, s.description, s.price, s.category, s.ordering, 
     s.state, s.checked_out, s.checked_out_time, s.created_by 
ORDER BY s.id 

Probabilmente dovrete di modificare la query un po ', ma spero che sia chiaro. Tieni presente che GROUP_CONCAT non è supportato da tutti i database ma MySQL ce l'ha.

Ancora, entrambe le soluzioni possono funzionare benissimo ed essere performante, ma aveva un campo separato da virgole creerà più problemi come questo. Vi consiglio caldamente di cambiare la struttura del vostro database. Leggi sulla normalizzazione del database se non hai familiarità con l'idea delle tabelle di collegamento.

+0

Wow grazie !, non ho mai pensato di collegare i tavoli ... Ehi, fallo nel modo giusto, naturalmente !, che senso ha fare qualcosa e sapere che è sbagliato? grazie mille .. mal provatelo in fretta: D –

Problemi correlati