2016-08-19 4 views
0

Ich habe zwei Tabellen in einer Datenbank, eine davon ist eine Liste von "Gebäuden", die Sie erstellen können. Die andere ist eine Liste von Gebäuden, die von Benutzern erstellt wurden.Wie kann ich Zeilen aus einer Tabelle anzeigen, die sich nicht in einer anderen Tabelle befinden?

Auf einer Seite (cityproduction.php) wird eine Liste der Gebäude angezeigt, die Sie erstellen können. Ich möchte, dass die Gebäude angezeigt werden, die Sie erstellen können, die Sie noch nicht erstellt haben.

Hier ist mein Code:

$sql = "SELECT * FROM [The list of built buildings] WHERE building_owner = '$user'"; 
$result = $conn->query($sql); 

if ($result->num_rows > 0) { 
while($row = $result->fetch_assoc()) { 
    $variable = $row["building_name"];  
} 

(...)

$sql = "SELECT * FROM [The list of ALL buildings] WHERE name != '$variable' ORDER BY id asc"; 
$result = mysqli_query($database,$sql) or die(mysqli_error($database)); 

while($rws = mysqli_fetch_array($result)){ 
echo $rws["name"]; (etc.) 

Was dies tut, ist nur eines der Gebäude nicht-zeigt, dass der Benutzer aufgebaut hat, nicht alle Sie.

Antwort

0

Warum verwenden Sie while nach der ersten Abfrage, es soll eine Liste oder nur ein einzelner Wert sein? denn wenn Sie $variable in Ihre zweite Abfrage wird es nur den Wert des letzten Wertes der Liste haben, werden Sie

bekommen
if ($result->num_rows > 0) { 

    $variable = array(); 

    while($row = $result->fetch_assoc()) { 

    $variable[] = $row["building_name"];  
} 

zweite Abfrage Beispiel:

foreach($variable as $building) { 

     $sql = "SELECT * FROM [The list of ALL buildings] WHERE name != '$building' ORDER BY id asc"; 
     $result = mysqli_query($database,$sql) or die(mysqli_error($database)); 
     $result = mysqli_fetch_assoc($result); 

     echo $result["name"]; 
    } 
+0

Ich möchte $ Variable zu al ist von all den Gebäuden, die von diesem Benutzer gebaut wurden - ich habe einfach angenommen, dass es als ein Array gespeichert wird, wie kann ich es als ein Array und nicht einen einzelnen Wert haben? – Daniel

+0

'$ variable = array();' vor dem 'while' und innerhalb des 'while's benutzen Sie es als' $ variable [] = $ row [' building_name ']; 'aber danach sollte Ihre zweite Abfrage in einer Schleife sein Um die Abfrage mit jedem Wert Ihres Arrays durchzuführen, könnte in diesem Fall eine 'foreach'-Schleife verwendet werden. –

+0

@DanterNetwork Sie können ein Array in Ihrem String nicht so verwenden. Sie könnten eine CSV-Datei erstellen und sie an eine SQL-Datei "in" übergeben. Dies öffnet Sie jedoch für SQL-Injektionen der zweiten Ebene. – chris85

1

Ohne die tatsächlichen Tabellennamen zu sehen oder das Schema es schwierig ist, genau zu beantworten, aber man könnte etwas in dieser Richtung versuchen:

SELECT * FROM `all_buildings` 
WHERE `id` not in ( 
    select `building_id` from `built_buildings` where `building_owner` = '$user' 
    ) 
ORDER BY `id` asc; 
+0

Danke! Ich hatte keine Ahnung, dass es "nicht" gab - dumm von mir. – Daniel

0

beide Tabellen Unter der Annahme haben eine Art von ID-Spalte zu beziehen sie, mit dieser Abfrage:

SELECT building_name, building_owner FROM 
    test.all_buildings a 
    LEFT JOIN test.built_buildings b ON a.id = b.building_id AND b.building_owner = ? 
ORDER BY building_owner DESC, building_name; 

(wo ? der Benutzer ist), können Sie alle Gebäude wählen, zuerst diejenigen, die gebaut wurden, von denen gefolgt, die nicht in einer Abfrage haben. Wenn Ihre Tabellen keine IDs wie diese haben, können Sie ihnen stattdessen den Namen geben; Es sollte funktionieren, solange die Namen eindeutig sind.

Wenn Sie die Zeilen abrufen, können Sie sie in "built" oder "not built" sortieren, indem Sie prüfen, ob die Zeile building_owner enthält.

if ($result->num_rows > 0) { 
    while($row = $result->fetch_assoc()) { 
     if ($row['building_owner']) { 
      $built[] = $row['building_name']; 
     } else { 
      $not_built = $row['building_name']; 
     } 
    } 
} 
1

Eine weitere Übersetzung Ihrer Frage in SQL (neben NOT IN) zu einer Correlated Subquery:

SELECT * FROM `all_buildings` AS a 
WHERE NOT EXISTS 
    ( 
    select * from `built_buildings` AS b 
    where a.`id` = b.`building_id` -- Outer Select correlated to Inner 
     and b.`building_owner` = '$user' 
) 
ORDER BY `id` asc; 

Der Hauptvorteil gegenüber NOT IN: es nur zweiwertig-Logik ist (NULL ignoriert = falsch), während NOT IN Drei-Wert-Logik verwendet (Vergleich zu NULL gibt unbekannt, die möglicherweise nicht zurück, was Sie erwarten)

Verwandte Themen