2016-09-09 2 views
0

Ich schreibe eine Bestandsaufnahme für unsere IT-Abteilung und ich bin nicht zuversichtlich, die Art, wie ich gehe, ist das Beste.SQL-Anweisung in verschachtelten While-Schleifen

Ich habe eine 'Produktgruppe' Tabelle und eine 'Produkt' Tabelle, die mit einer ID verbunden sind (eine Produktgruppe zu vielen Produkten) Produktgruppe zum Beispiel LaserJet Pro 400 und Produkte wären die einzelnen Verbrauchsmaterialien .. schwarz, magenta , cyan usw.

Also was passiert ist, habe ich eine while-Schleife für die Anzeige der Gruppen und dann eine geschachtelte While-Schleife für die Anzeige der Produkte innerhalb dieser Gruppe.

Worüber ich mir Sorgen gemacht habe ist, dass es viele Aussagen im Schnellfeuer gibt, es scheint kein Problem mit der Leistung in diesem frühen Stadium zu geben, aber ich bin unsicher .. ist das akzeptabel? Gibt es einen besseren Weg?

foreach ($_POST['BeginLocation'] as $key => $value) {$LocationID = $key;} 

echo '<div class="nmform"><form name="StockTake" action="index.php" method="post" enctype="multipart/form-data">'; 

include "../DBCon/RDPNearMisses.php"; 

$GetProductGroups = sqlsrv_query($NMDB, "select distinct PD.ProductGroupID, PG.GroupName 
             from [JobObservations].[dbo].[ITStk.Products] as PD 
             inner join [JobObservations].[dbo].[ITStk.ProductGroups] as PG on PD.ProductGroupID = PG.ProductGroupID 
             where PD.LocationID = $LocationID"); 

         if($GetProductGroups === false) { 
          if(($errors = sqlsrv_errors()) != null) { 
           foreach($errors as $error) { 
            echo "SQLSTATE: ".$error[ 'SQLSTATE']."<br />"; 
            echo "code: ".$error[ 'code']."<br />"; 
            echo "message: ".$error[ 'message']."<br />"; 
           } 
          } 
         } 

         while ($row = sqlsrv_fetch_array($GetProductGroups)) {echo '<h4>'.$row['GroupName'].'</h4>'; 
               $ProductGroupID = $row['ProductGroupID']; 

               $GetProducts = sqlsrv_query($NMDB, "select PD.ProductID, PD.ProductGroupID, PD.ProductCode, PD.ProductDescription 
               from [JobObservations].[dbo].[ITStk.Products] as PD 
               inner join [JobObservations].[dbo].[ITStk.ProductGroups] as PG on PD.ProductGroupID = PG.ProductGroupID 
               inner join [JobObservations].[dbo].[ITStk.Locations] as LC on PD.LocationID = LC.LocationID 
               where PD.LocationID = $LocationID 
               and PD.ProductGroupID = $ProductGroupID 
               order by LC.LocationDescription asc, PG.GroupName asc, PD.ProductCode asc"); 

               if($GetProducts === false) { 
                if(($errors = sqlsrv_errors()) != null) { 
                 foreach($errors as $error) { 
                  echo "SQLSTATE: ".$error[ 'SQLSTATE']."<br />"; 
                  echo "code: ".$error[ 'code']."<br />"; 
                  echo "message: ".$error[ 'message']."<br />"; 
                 } 
                } 
               } 
               echo '<table><th>Code</th><th>Description</th><th>Qty</th>'; 
               while ($row1= sqlsrv_fetch_array($GetProducts)) {echo '<tr><td>'.$row1['ProductCode'].'</td><td>'.$row1['ProductDescription'].'</td><td><select name="'.$row1['ProductID'].'"><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option></select></td></tr>';} 
               echo '</table>'; 


         } 
         echo '<input type="Submit" name="SubmitStock"></form>'; 
         sqlsrv_close($NMDB); 
     echo '</div>'; 
+0

Es gibt viele Probleme mit dem Code hier. Zuerst müssen Sie über parametrisierte Abfragen lesen, verstehen und starten. Zweitens könnten Sie diese ganze geschachtelte Loop-Lösung wahrscheinlich in eine einzige Abfrage umwandeln. Wenn Sie wirklich Hilfe benötigen, lesen Sie diesen Artikel. http://spaghettidba.com/2015/04/24/how-to-post-at-sql-question-on-a-public-forum/ –

+0

Ich könnte es leicht zu einer einzigen Abfrage aus einer SQL-Sicht zu machen , das Problem ist, wie ich es mit php mit einem Gruppennamen Überschrift dann Subproducts präsentieren. –

+0

Sean, danke für die Erwähnung parametrisierter Abfragen. Meine Umgebung ist ziemlich risikoarm für SQL-Injection, da ich nicht im Web bin, aber ich werde das übernehmen. Leider habe ich bei Google PHP unterrichtet, so dass ich immer noch auf vieles stoße, das für andere und Neuigkeiten für mich grundlegend ist. –

Antwort

1

Während Ihre Daten klein ist und die Anzahl der Gruppen pro Ort ist klein, werden Sie wahrscheinlich keinen Unterschied bemerken, aber als die Anzahl der Gruppen pro Standort Änderungen können Sie wollen 1 Abfrage Umschalten zu berücksichtigen und eine while-Schleife:

SELECT DISTINCT 
    PD.ProductID, 
    PG.GroupName, 
    PD.ProductGroupID, 
    PD.ProductCode, 
    PD.ProductDescription 
FROM [JobObservations].[dbo].[ITStk.Products] AS PD 
INNER JOIN [JobObservations].[dbo].[ITStk.ProductGroups] AS PG ON PD.ProductGroupID = PG.ProductGroupID 
INNER JOIN [JobObservations].[dbo].[ITStk.Locations] AS LC ON PD.LocationID = LC.LocationID 
WHERE PD.LocationID = $LOCATIONID; 

gut funktionieren würde, da es Ihnen einen Datensatz enthält, Ihren ungenutzten Gruppennamen und die Produkt-ID und Produzieren Beschreibung bekommt, die Sie in Ihrer Tabelle verwenden.

Außerdem, wenn die Tabelle ITStk.Locations wird nur zur Begrenzung der Datensätze, wo eine LocationID ist eigentlich in der Locations Tabelle beigetreten, dann ist es nicht notwendig, dass hier verbunden werden. Sie verwenden keines der Felder, um Ergebnismengen oder SELECT einzuschränken.

Fast jedes Mal, wenn Sie ein Recordset greifen und beim Lesen/Loopen des Datensatzes mehr SQL ausgeben, können Sie dies in eine einzige SQL-Anweisung umwandeln.

Um Ihre GroupName als Überschrift über Tabellen, in dem 1 while-Schleife erhalten Sie so etwas wie das folgende tun könnte (Verzeihen Sie mir, es ist ein paar Jahre her ist, seit ich PHP geschrieben):

$GetProductGroups = sqlsrv_query($NMDB, "SELECT DISTINCT 
             PD.ProductID, 
             PG.GroupName, 
             PD.ProductGroupID, 
             PD.ProductCode, 
             PD.ProductDescription 
            FROM [JobObservations].[dbo].[ITStk.Products] AS PD 
            INNER JOIN [JobObservations].[dbo].[ITStk.ProductGroups] AS PG ON PD.ProductGroupID = PG.ProductGroupID 
            INNER JOIN [JobObservations].[dbo].[ITStk.Locations] AS LC ON PD.LocationID = LC.LocationID 
            WHERE PD.LocationID = $LOCATIONID 
            ORDER BY GroupName;"); 

if($GetProductGroups === false) { 
    if(($errors = sqlsrv_errors()) != null) { 
     foreach($errors as $error) { 
      echo "SQLSTATE: ".$error[ 'SQLSTATE']."<br />"; 
      echo "code: ".$error[ 'code']."<br />"; 
      echo "message: ".$error[ 'message']."<br />"; 
     } 
    } 
} 

while ($row = sqlsrv_fetch_array($GetProductGroups)) { 

    /*If the groupname of the current record is different then the last record's group name (notice order by on query) then echo out the header and start a new table*/ 
    if ($groupname != $row['GroupName']) { 
     echo '<h4>'.$row['GroupName'].'</h4>'; 
     echo '<table><th>Code</th><th>Description</th><th>Qty</th>'; 
    } 

    /*echo out the row into the table*/ 
    echo '<tr><td>'.$row['ProductCode'].'</td><td>'.$row['ProductDescription'].'</td><td><select name="'.$row1['ProductID'].'"><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option><option>0</option></select></td></tr>'; 


    /*again if we started a new table because the groupname is new in the recordset, then close the table*/ 
    if ($groupname != $row['GroupName']) {   
     echo '</table>'; 
    } 
    /*Capture group name for future iterations*/  
    $groupname = $row['GroupName']; 

} 

echo '<input type="Submit" name="SubmitStock"></form>'; 
sqlsrv_close($NMDB); 
echo '</div>'; 
+0

Sie haben Recht, ich musste die Standorttabelle nicht einschließen, da ich nur die Standort-ID für die Filterung referenziere. Der Grund dafür sind zwei Abfragen, die zuerst die Liste der möglichen Produktgruppen für die Standort-ID (auf der vorherigen Seite ausgewählt) und die verschachtelte While-Loop-Abfrage die Produkte unter der Überschrift jeder Produktgruppe anzeigen.Ich könnte die gleichen Informationen mit einer Abfrage erhalten, aber ich weiß nicht, wie ich es auf der Seite mit GroupName organisieren würde, die eine Überschrift und eine Liste von Produkten darunter wie es jetzt ist. Beachten Sie, dass GroupName vor der verschachtelten while-Schleife angezeigt wird. –

+0

Sie könnten das in Ihrer while-Schleife tun. Ergreifen Sie die Gruppe in eine Variable, und wenn es der erste Datensatz ODER die aktuelle Gruppe ist nicht gleich der gespeicherten Gruppe in der Variablen, dann drucken Sie einen neuen Header. Das ist viel schneller für PHP zu analysieren, dann wird es sein, die Datenbank nach einem neuen Recordset abzufragen. Abfragen sind sehr teuer, eine Variable und eine if-Anweisung ist billig. Sie werden wahrscheinlich zunächst keinen großen Unterschied bemerken, aber wenn die Anzahl der Gruppen pro Standort zunimmt, wird Ihre Seite immer mehr tuckern, wenn Sie mit einer Abfrage pro Gruppe fortfahren. – JNevill

+0

Oh! Ich sehe diesen Gruppennamen jetzt im H4-Tag aussprechen. Ich werde diesen Teil der Frage bearbeiten, aber die Lösung steht immer noch. – JNevill

Verwandte Themen