Tabellenübergreifende MySQL-Abfrage..
lima-city → Forum → Programmiersprachen → PHP, MySQL & .htaccess
abfrage
array
biologie
code
dank
datum
erreichen
fach
gymnasium
hilfe
inhalt
kategorie
lehrer
liste
machen
ordern
schulart
spalten
tabelle
url
-
Hallo,
ich würde gerne eine Seite machen, auf welcher verschiedene Kategorien angezeigt werden...
meine Datenbank sieht ganz grob so aus:
Tabelle "kategorie" mit Spalten: id, name ...
Tabelle "inhalte" mit Spalten id, name, kategorie ...
und die Tabelle "kategorie" soll nun ausgegeben werden, aber nur solche Einträge, bei welchen
in der Tabelle "inhalte" mindestens 1 Eintrag vorhanden ist (kategorie)
bsp:
kategorie:
id, name
1 , "Test"
2, "Hallo"
inhalte:
id, kategorie, name
1, 2, "Hay"
2, 2, "Wie gehts?"
und dann soll jetzt bei einer Abfrage von "kategorie" nur der Eintrag 2, "Hallo" zurückgegebn werden,
weil es in der Tabelle inhalte für den 1. Eintrag "Test" keine Einträge gibt...
Wie setze ich das mit einer SQL Abfrage am Besten um?
Danke schonmal und schöne Grüße, -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage
-
Hallo fr34qy,
'INNER JOIN' ist Dein Freund. Damit kannst Du die Werte aus zwei Tabellen mit Bedingungen zusammenführen.
Für Dein Beispiel sieht das dann folgendermaßen aus:
Die Verknüpfungsbedingung wird hierbei im 'ON'-Abschnitt angegeben.SELECT kategorie.name FROM kategorie INNER JOIN inhalte ON kategorie.id = inhalte.kategorie
Edit:
Wenn jede Kategorie maximal einmal ausgegeben werden soll, dann kann man das entweder mit dem 'DISTINCT'-Schlüsselwort:
oder mittels 'GROUP BY'-Klausel erreichen:SELECT DISTINCT kategorie.name FROM kategorie INNER JOIN inhalte ON kategorie.id = inhalte.kategorie
SELECT kategorie.name FROM kategorie INNER JOIN inhalte ON kategorie.id = inhalte.kategorie GROUP BY kategorie.name
Beitrag zuletzt geändert: 31.3.2012 21:57:26 von darkpandemic -
ich kann schon förmlich spüren, wie meine Scripte jetzt um einiges einfacher werden :)
vielen dank, ich probier das die tage mal aus...
noch eine Frage hätte ich:
Wenn ich in einer Tabelle mit den Spalten id,name,datum eine Zeile auswähle,
und die dann in eine andere Tabelle mit den Spalten id,name,datum,spalte1,spalte2
kopieren/einfügen möchte, wobei alle spalten gleich übernommen werden sollen, und nur spalte1 und spalte2 mit vom php Script festgelegten werten beschrieben werden sollen,
wie mach ich das da am geschicktesten? gibts da auch ne einfache Lösung mit SQL? -
Hallo fr34qy,
wenn in spalte1 und spalte2 immer der gleiche Wert eingetragen werden soll, dann kannst Du das z.B. so machen:
D.h. nach 'INSERT INTO tabelle(feld1, feld2, ...)' kann eine beliebige Abfrage folgen (auch mit WHERE-Abschnitt) vorausgesetzt, dass die Anzahl der Spalten und die Datentypen übereinstimmen (oder auf einfache Weise konvertierbar sind). Die Werte 'foo' und 'bar' kannst Du dann per PHP in die Abfrage eintragen. Wenn die Werte für die Spalten 'spalte1' und 'spalte2' von einem oder mehreren der selektierten Felder abhängen, dann funktioniert das auch noch, sofern sich der einzutragende Wert mit Hilfe von SQL beschreiben lässt. Z.B.:INSERT INTO tabelle2(id, name, datum, spalte1, spalte2) SELET id, name, datum, "foo", "bar" FROM tabelle1
INSERT INTO tabelle2(id, name, datum, spalte1, spalte2) SELET id, name, datum, IF(id > 20, 'foo', 'bar'), CONCAT('Monat:', CAST(DATE_FORMAT(datum, '%c') AS CHAR(2)) FROM tabelle1
-
Danke darkpandemic,
das INSERT funktioniert schon wunderbar!
Allerdings macht mir die komplexere Anweisung vom Anfang noch etwas zu schaffen,
vorallem sie abzuändern und an meine Wünsche anzupassen...
Ich habe konkret 3 Tabellen mit diesen Spalten:
tests_schularten --> id, name, aktiv
tests_faecher --> id, schulart, name
tests_lehrer --> id, schulart, kuerzel, name, fach1, fach2
Nun würde ich gerne eine Liste erstellen,
welche zuerst einmal alle (aktiven -> aktiv=1) Schularten nimmt,
dann in diesen die Fächer alphabetisch (ASC) ausgibt und als Unterpunkte jeweils die
Lehrer nennt, welche dieses Fach unterrichten (fach1,fach2),
allerdings mit deren id, da das ganze in einer DropDown-liste stehen soll..
Mein (kläglich gescheiterter) Versuch:
SELECT `tests_faecher`.`id`,`tests_faecher`.`name`,`tests_faecher`.`schulart` FROM `tests_faecher` UNION ALL SELECT `tests_lehrer`.`id`, `tests_lehrer`.`kuerzel` FROM `tests_lehrer` INNER JOIN `tests_lehrer` ON `tests_faecher`.`id` = `tests_lehrer`.`fach1` OR `tests_faecher`.`id` = `tests_lehrer`.`fach2` SORT BY `tests_faecher`.`schulart` ASC,`tests_faecher`.`name` ASC
funktioniert aber leider nicht...
SELECT `tests_faecher`.`id`,`tests_faecher`.`name`,`tests_faecher`.`schulart` FROM `tests_faecher` INNER JOIN `tests_lehrer` ON `tests_faecher`.`id` = `tests_lehrer`.`fach1` OR `tests_faecher`.`id` = `tests_lehrer`.`fach2` GROUP BY `tests_faecher`.`schulart` ASC,`tests_faecher`.`name` ASC
hingegen hat noch wunderbar funktioniert und jedes Fach schön alphabetisch und nach schulart sortiert
Kann man das ganze mit 1 SQL-befehl überhaupt lösen, oder ist es besser, wenn man nochmal ne 2. Abfrage macht?
Danke schonmal für deine Hilfe, mit so komplexeren SQL-Anweisungen kenn ich mich so garnicht aus...
Das original PHP-Script, mit welchem ich das bisher gelöst habe, sieht so aus:
(vllt hilfts dir zu verstehn, was ich erreichen möchte - ich finde, es is ziemlich aufgebläht,
weshalb ich auch hoffe, dass durch einen ausgeklügelten SQL-befehl einfacher lösen zu können...)
<select name="lehrer" size="1"> <?php $lehrer=false; $result = mysql_query ("SELECT * FROM `tests_schularten`"); if (mysql_num_rows ($result) > 0) { echo '<option value="0">Bitte Lehrer auswählen...</option>'; for ($i=0; $i<mysql_num_rows($result); $i++) { $array = mysql_fetch_array($result); $schoolid = $array["id"]; $schoolname = $array["name"]; $result2 = mysql_query ("SELECT * FROM `tests_faecher` WHERE (schulart = ".$schoolid.") ORDER BY `name` ASC"); if (mysql_num_rows ($result2) > 0) { echo '<optgroup label="'.$schoolname.'" class="og1">'; for ($i2=0; $i2<mysql_num_rows($result2); $i2++) { $array2 = mysql_fetch_array($result2); $fachid = $array2["id"]; $fachname = $array2["name"]; $result3 = mysql_query ("SELECT * FROM `tests_lehrer` WHERE (fach1 = ".$fachid." OR fach2 = ".$fachid.") ORDER BY kuerzel ASC"); if (mysql_num_rows ($result3) > 0) { echo '<optgroup label=" '.$fachname.'" class="og2">'; for ($i3=0; $i3<mysql_num_rows($result3); $i3++) { $array3 = mysql_fetch_array($result3); $selected='';if($modus!=0 && $array3["id"]==$pLehrer)$selected=' selected'; echo '<option value="'.$array3["id"].'"'.$selected.'>'.$array3["kuerzel"].'</option>'; $lehrer=true; } echo '</optgroup>'; } } echo '</optgroup>'; } else { $result3 = mysql_query ("SELECT * FROM `tests_lehrer` WHERE (schulart = ".$schoolid.") ORDER BY kuerzel"); if (mysql_num_rows ($result3) > 0) { echo '<optgroup label="'.$schoolname.'" class="og1">'; for ($i3=0; $i3<mysql_num_rows($result3); $i3++) { $array3 = mysql_fetch_array($result3); $selected='';if($modus!=0 && $array3["id"]==$pLehrer)$selected=' selected'; echo '<option value="'.$array3["id"].'"'.$selected.'>'.$array3["kuerzel"].'</option>'; $lehrer=true; } echo '</optgroup>'; } } } } else { $result2 = mysql_query ("SELECT * FROM `tests_lehrer` ORDER BY kuerzel"); if (mysql_num_rows ($result2) > 0) { for ($i2=0; $i2<mysql_num_rows($result2); $i2++) { $array2 = mysql_fetch_array($result2); $selected='';if($modus!=0 && $array2["id"]==$pLehrer)$selected=' selected'; echo '<option value="'.$array2["id"].'"'.$selected.'>'.$array2["kuerzel"].'</option>'; $lehrer=true; } } } if (!$lehrer) echo '<option value="0">Keine Lehrer vorhanden...</option>'; ?> </select>
-
Hallo fr34qy,
an und für sich lässt sich eine Abfrage bauen, die sowas macht:
(Ist nicht getestet, daher keine Garantie)SELECT DISTINCT tests_schularten.name AS schulart, tests_faecher.name AS fach, tests_lehrer.name AS lehrer, tests_lehrer.id AS lehrer_id FROM ( tests_schularten INNER JOIN tests_faecher ON tests_schularten.id = tests_faecher.schulart ) INNER JOIN tests_lehrer ON tests_schulart.id = tests_lehrer.schulart AND ( tests_faecher.id = tests_lehrer.fach1 OR tests_faecher.id = tests_lehrer.fach2 ) WHERE tests_schularten.aktiv = 1 ORDER BY tests_schulart.name, tests_faecher.name, tests_lehrer.name;
Aber Deine Anforderung klingt eigentlich anders. Es schein ja so zu sein, dass ein Benutzer erst eine (aktive) Schulart auswählt, dann von den zugehörigen Fächern eines auswählt und sich zum Schluß einen Lehrer aussucht. Also hat man entweder zwei Drop-Down-Listen und ein normale Liste oder drei Drop-Down-Listen. In dem Fall ist die empfehlenswerte vorgehensweise eigentlich die, die Du sowieso schon gemacht hast:
Für jedes Drow-Down-Feld eine Abfrage:
Für die Auswahl der Schulart:
Wenn die Schulart gewählt wurde, für die Fächer:SELECT id, name FROM tests_schulart WHERE tests_schulart.aktiv = 1 ORDER BY name
Und zum Schluß die passenden Lehrer:SELECT id, name FROM test_faecher WHERE schulart = <id der gewählten Schulart> ORDER BY name
Aus Sicht der Oberfläche/Webseite sollte der Ablauf dann eigentlich so sein:SELECT id, name FROM tests_lehrer WHERE schulart = <id der gewählten Schulart> AND ( fach1 = <id des gewählten Faches> OR fach2 = <id des gewählten Faches>) ORDER BY name
Wenn die Seite ausgeliefert wird, dann ist das 'Schularten'-Drop-Down gefüllt und die anderen Drop-Downs sind deaktiviert.
Wenn eine Schulart ausgewählt wird (Change-Ereignis oder wie das in Javascript heißt), dann werden mittels XMLHttpRequest die zugehörigen Werte für das 'Fächer'-Drop-Down geladen und dieses Feld aktiviert. Wenn ein Fach gewählt wurde, dann macht man dasselbe nochmal für die Lehrer. D.h. eigentlich benötigst Du noch eine zweite PHP-Datei, die nur die Abfragen 2 und 3 nach Bedarf ausführt und die Daten als simplen Text zurückschickt.
Beitrag zuletzt geändert: 4.4.2012 20:10:46 von darkpandemic -
Hallo darkpandemic,
ja, ich habe mir auch schon überlegt, das Ganze mit jQuery und AJAX umzusetzen,
wollte aber eigentlich eine Methode, die kein JS benötigt.
Meine bisherige Lösung (und das, was ich so in etwa erreichen wollte), sieht so aus:
http://img585.imageshack.us/img585/5929/lehrerdropdown.jpg
SELECT DISTINCT tests_schularten.name AS schulart, tests_faecher.name AS fach, tests_lehrer.kuerzel AS lehrer, tests_lehrer.id AS lehrer_id FROM ( tests_schularten INNER JOIN tests_faecher ON tests_schularten.id = tests_faecher.schulart ) INNER JOIN tests_lehrer ON tests_schularten.id = tests_lehrer.schulart AND ( tests_faecher.id = tests_lehrer.fach1 OR tests_faecher.id = tests_lehrer.fach2 ) WHERE tests_schularten.aktiv =1 ORDER BY tests_schularten.name, tests_faecher.name, tests_lehrer.name
paar kleine Sachen, wie tabellennamen musste man teilweise noch ändern, aber das funktioniert prinzipiell
sieht jetzt aber schon leicht komplex aus muss man sagen
Ausgabe: (mit schleife und print_r)
Array ( [schulart] => Gymnasium [fach] => Biologie [lehrer] => Bök [lehrer_id] => 9 ) Array ( [schulart] => Gymnasium [fach] => Biologie [lehrer] => Gn [lehrer_id] => 14 ) Array ( [schulart] => Gymnasium [fach] => Biologie [lehrer] => Kra [lehrer_id] => 4 ) Array ( [schulart] => Gymnasium [fach] => Biologie bilingual [lehrer] => Gn [lehrer_id] => 14 ) Array ( [schulart] => Gymnasium [fach] => Chemie [lehrer] => Kra [lehrer_id] => 4 ) Array ( [schulart] => Gymnasium [fach] => Deutsch [lehrer] => Sim [lehrer_id] => 8 ) Array ( [schulart] => Gymnasium [fach] => Deutsch [lehrer] => Ub [lehrer_id] => 2 ) Array ( [schulart] => Gymnasium [fach] => Englisch [lehrer] => Judt [lehrer_id] => 15 ) Array ( [schulart] => Gymnasium [fach] => Englisch [lehrer] => Kun [lehrer_id] => 5 ) Array ( [schulart] => Gymnasium [fach] => Französisch [lehrer] => Kun [lehrer_id] => 5 ) Array ( [schulart] => Gymnasium [fach] => Französisch [lehrer] => Mud [lehrer_id] => 3 ) [...] Array ( [schulart] => Realschule [fach] => TestRS [lehrer] => LRS [lehrer_id] => 17 ) Array ( [schulart] => Werkrealschule [fach] => TestWRS [lehrer] => LHS [lehrer_id] => 16 )
dass müsste ich dann ja jetzt nurnoch verarbeiten :)
würde dann wohl auf sowas wie
$schulart_old und if ($schulart != $schulart_old) { /* alte optgroup schließen, neue anfangen */ }
oder?
vielleicht überleg ich mir das aber wirklich mit AJAX... auch wenn ich ned son Fan von JS is, weils eben Browserabhängig is, und ja auch aus sein kann
das Ereignis müsste onChange heißen jop..
dann werd ich mich wohl iwann mal bisschen mit JS und AJAX beschäftigen ;)
wär dann aber wahrscheinlich nicht schlecht, die jetzige abfrage mit <noscript> zu behalten oder?
Danke nochmal für deine Mühen :) Auf so eine komplexe SQL-Abfrage wär ich von selber nie gekommen :) -
Hallo fr34qy,
nachdem die Abfrage ja funktioniert hast Du ja jetzt beide Möglichkeiten
Ich habe ja nur anhand Deine Beschreibung geraten, was es wohl werden soll. Jetzt wo ich den Screenshot gesehen habe, kann ich mir mehr darunter vorstellen. Das einzige wobei man evtl. aufpassen muss ist, dass die Liste aufgrund der Länge nicht unübersichtlich wird.
Grundsätzlich finde ich es aber immer gut, wenn eine Webseite auch ohne Javascript funktioniert. Von daher überlasse ich Dir jetzt die Entscheidung und wünsche noch viel Erfolg bei dem Projekt. -
Hallo darkpandemic,
ich habe das natürlich gleich umgesetzt, und siehe da, es funktioniert genauso gut, wie der alte Code und sieht auch noch schöner, übersichtlicher und effizienter aus lediglich die SQL-Anweisung ist jetzt etwas größer geworden..
<select name="lehrer" size="1"> <?php $result = mysql_query("SELECT DISTINCT tests_schularten.name AS schulart, tests_faecher.id AS fach_id, tests_faecher.name AS fach, tests_lehrer.kuerzel AS lehrer, tests_lehrer.id AS lehrer_id FROM ( tests_schularten INNER JOIN tests_faecher ON tests_schularten.id = tests_faecher.schulart ) INNER JOIN tests_lehrer ON tests_schularten.id = tests_lehrer.schulart AND ( tests_faecher.id = tests_lehrer.fach1 OR tests_faecher.id = tests_lehrer.fach2 ) WHERE tests_schularten.aktiv =1 ORDER BY tests_schularten.name, tests_faecher.name, tests_lehrer.name"); if (mysql_num_rows ($result) > 0) { echo '<option value="0">Bitte Lehrer auswählen...</option>'; $schulart_old = ""; $fachid_old = ""; for ($i=1; $i<=mysql_num_rows ($result); $i++) { $row=mysql_fetch_assoc($result); $schulart = $row["schulart"]; $fach = $row["fach"]; $fachid = $row["fach_id"]; $lkuerzel = $row["lehrer"]; $lid = $row["lehrer_id"]; if ($i==1) { $schulart_old = $schulart; $fachid_old = $fachid; echo '<optgroup label="'.$schulart.'" class="og1">'; echo '<optgroup label=" '.$fach.'" class="og2">'; } if ($fachid_old != $fachid) { if ($schulart_old != $schulart) { echo '</optgroup></optgroup>'; echo '<optgroup label="'.$schulart.'" class="og1">'; echo '<optgroup label=" '.$fach.'" class="og2">'; } else { echo '</optgroup>'; echo '<optgroup label=" '.$fach.'" class="og2">'; } $fachid_old = $fachid; $schulart_old = $schulart; } $selected='';if(isset($pLehrer) && $lid==$pLehrer)$selected=' selected'; echo '<option value="'.$lid.'"'.$selected.'>'.$lkuerzel.'</option>'; } echo '</optgroup></optgroup>'; } else echo '<option value="0">Keine Lehrer vorhanden...</option>'; ?> </select>
Und nochmal vielen Dank für deine Hilfe :) so gefällt mir das schon viel besser (hat konkret 15 Zeilen gespart, trotz mehrzeiliger SQL anweisung)
Auswahl mithilfe von AJAX sitzt ab heute auch auf meiner ToDo.Liste, allerdings soll die Alternativlösung weiterhin bestehen bleiben :) -
Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!
lima-city: Gratis werbefreier Webspace für deine eigene Homepage