2012-11-30 8 views
6

Mi è stato detto che è una cattiva pratica utilizzare una query (selezione) all'interno di un ciclo perché rallenta le prestazioni del server.PHP Alternativa all'utilizzo di una query all'interno di un ciclo

ho un array come

Array ([1] => Los Angeles) 
Array ([2] =>New York) 
Array ([3] => Chicago) 

Questi sono solo 3 indici. La matrice che sto usando non ha una dimensione costante, quindi a volte può contenere fino a 20 indici.

In questo momento, quello che sto facendo è (questo non è tutto il codice, ma l'idea di base)

  1. ciclo For
  2. di query al server e selezionare tutti i nomi delle persone che vivono in " Los Angeles"
  3. stampare i nomi fuori

uscita sarà simile a questa:

Los Angeles 
     Michael Stern 
     David Bloomer 
     William Rod 

New York 
     Kary Mills 

Chicago 
     Henry Davidson 
     Ellie Spears 

So che è un metodo davvero inefficiente perché potrebbe essere un sacco di query, man mano che la tabella si ingrandisce più tardi.

Quindi la mia domanda è, c'è un modo migliore, più efficiente per SELEZIONARE le informazioni in base alle cose all'interno di un array che può essere di qualsiasi dimensione?

+0

è possibile utilizzare un http: //fr2.php di preparazione.net/manual/it/pdo.prepare.php – Ajouve

+0

Le persone, 8 risposte non accettate vanno perfettamente bene. OP sa già (come ha fatto 5 volte) come accettare una risposta. È molto probabile che non abbia avuto una risposta sufficiente alle sue altre domande. Dagli una pausa, per favore. –

+0

Grazie per avermi difeso, Madara, sei così gentile: ...) – r1nzler

risposta

4

per aggiungere ulteriore al MrCodes risposta, se si inizia con una serie: -

$Cities = array(1=>'Los Angeles', 2=>'New York', 3=>'Chicago'); 
$query = "SELECT town, personname FROM people WHERE town IN('".implode("','", $Cities)."') ORDER BY town"; 
if ($sql = $mysqliconnection->prepare($query)) 
{ 
    $sql->execute(); 
    $result = $sql->get_result(); 
    $PrevCity = ''; 
    while ($row = $result->fetch_assoc()) 
    { 
     if ($row['town'] != $PrevCity) 
     { 
      echo $row['town']."<br />"; 
      $PrevCity = $row['town']; 
     } 
     echo $row['personname']."<br />"; 
    } 
} 

Come un database d esign problema, probabilmente dovresti avere i nomi delle città in una tabella separata e il tavolo per la persona contiene l'id della città piuttosto che il nome della città reale (rende la convalida più facile, più veloce e con meno probabilità di mancare record perché qualcuno ha digitata male la loro città natale)

+0

Amico ... sei la bomba ... lol – r1nzler

0

Questo è lo scopo delle dichiarazioni preparate. Si associa un segnaposto a un valore e lo si utilizza come una variabile, con la stessa query. Poiché la query non è stata modificata, si riduce al minimo la comunicazione con il server mysql, con conseguente aumento dell'efficienza.

Esempio con DOP:

$cities = array(
    "Los Angeles", 
    "New York", 
    "Chicago" 
); 

try { 
    //Change database parameters here (user, pass, database name) 
    $db = new PDO("mysql:host=localhost;dbname=users", "user", "pass"); 
    $db->setAttribute(PDO::ATTR_ERRMODE, PDO::ERRMODE_EXCEPTION); 
    $db->setAttribute(PDO::ATTR_EMULATE_PREPARES, false); 

    $stmt = $db->prepare("SELECT * FROM `users` WHERE `city` = :city"); 

    foreach ($cities as $city) { 
     $stmt->bindValue(":city", $city); 
     $stmt->execute(); 

     $result = $stmt->fetchAll(PDO::FETCH_ASSOC); 
     //Output data here. You can format it however you'd like 
     var_dump($city, $result); 
    } 

} 
catch (PDOException $e) { 
    //Error handling here 
} 
+0

Quindi stai dicendo che il metodo che ho fatto nel mio post va bene? – r1nzler

4

Usare un IN query, che catturerà tutti i risultati in una singola query:

SELECT * FROM people WHERE town IN('LA', 'London', 'Paris') 
+0

E come si fa a produrre i risultati nel modo desiderato? Questa risposta non riesce completamente a rispondere alla domanda che l'OP ha posto. – eggyal

+1

@eggyal la vera domanda è come migliorare l'efficienza delle domande ripetute, a cui ho risposto. OP non ha mai realmente chiesto come produrlo in quel modo. Se l'OP ha problemi specifici con l'output, sarei lieto di aiutarti. – MrCode

1

Come @MrCode mentions, è possibile utilizzare operatore di MySQL IN() per andare a prendere record per tutte le città desiderate in una volta sola, ma se si è quindi sort i risultati principalmente per città, è possibile eseguire il looping del set di risultati tenendo traccia dell'ultima città vista e emettendo la nuova città quando è prima ntered.

Utilizzando PDO, insieme con la funzione di MySQL FIELD() per garantire che il gruppo di risultati è nello stesso ordine come l'array originale (se non si cura di questo, si può semplicemente fare ORDER BY city, che sarebbe molto più efficiente, soprattutto con un altro indice idoneo sulla colonna city):

$arr = ['Los Angeles', 'New York', 'Chicago']; 
$placeholders = rtrim(str_repeat('?, ', count($arr)), ', '); 

$dbh = new PDO("mysql:dbname=$dbname", $username, $password); 
$qry = $dbh->prepare(" 
    SELECT city, name 
    FROM  my_table 
    WHERE city IN ($placeholders) 
    ORDER BY FIELD(city, $placeholders) 
"); 

if ($qry->execute(array_merge($arr, $arr))) { 

    // output headers 
    echo '<ul>'; 

    $row = $qry->fetch(); 
    while ($row) { 
    $current_city = $row['city']; 

    // output $current_city initialisation 
    echo '<li>'.htmlentities($current_city).'</li><ul>'; 
    do { 
     // output name $row 
     echo '<li>'.htmlentities($row['name']).'</li>'; 
    } while ($row = $qry->fetch() and $row['city'] == $current_city); 
    // output $current_city termination 
    echo '</ul>'; 
    } 

    // output footers 
    echo '</ul>'; 
} 
+0

Grazie amico, questo mi ha davvero aiutato molto! : D – r1nzler

Problemi correlati