kostenloser Webspace werbefrei: lima-city


Tabellenübergreifende MySQL-Abfrage..

lima-cityForumProgrammiersprachenPHP, MySQL & .htaccess

  1. Autor dieses Themas

    fr34qy

    fr34qy hat kostenlosen Webspace.

    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,
  2. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

  3. 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:
    SELECT kategorie.name 
    FROM kategorie INNER JOIN inhalte
        ON kategorie.id = inhalte.kategorie
    Die Verknüpfungsbedingung wird hierbei im 'ON'-Abschnitt angegeben.

    Edit:
    Wenn jede Kategorie maximal einmal ausgegeben werden soll, dann kann man das entweder mit dem 'DISTINCT'-Schlüsselwort:
    SELECT DISTINCT kategorie.name 
    FROM kategorie INNER JOIN inhalte
        ON kategorie.id = inhalte.kategorie
    oder mittels 'GROUP BY'-Klausel erreichen:
    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
  4. Autor dieses Themas

    fr34qy

    fr34qy hat kostenlosen Webspace.

    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?
  5. Hallo fr34qy,

    wenn in spalte1 und spalte2 immer der gleiche Wert eingetragen werden soll, dann kannst Du das z.B. so machen:
    INSERT INTO tabelle2(id, name, datum, spalte1, spalte2)
        SELET id, name, datum, "foo", "bar" 
        FROM tabelle1
    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, IF(id > 20, 'foo', 'bar'),
            CONCAT('Monat:', CAST(DATE_FORMAT(datum, '%c') AS CHAR(2)) 
        FROM tabelle1

  6. Autor dieses Themas

    fr34qy

    fr34qy hat kostenlosen Webspace.

    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&auml;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="&nbsp;&nbsp;'.$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>
  7. Hallo fr34qy,

    an und für sich lässt sich eine Abfrage bauen, die sowas macht:
    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;
    (Ist nicht getestet, daher keine Garantie)
    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:
    SELECT id, name 
    FROM tests_schulart 
    WHERE tests_schulart.aktiv = 1
    ORDER BY name
    Wenn die Schulart gewählt wurde, für die Fächer:
    SELECT id, name
    FROM test_faecher
    WHERE schulart = <id der gewählten Schulart>
    ORDER BY name
    Und zum Schluß die passenden Lehrer:
    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
    Aus Sicht der Oberfläche/Webseite sollte der Ablauf dann eigentlich so sein:
    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
  8. Autor dieses Themas

    fr34qy

    fr34qy hat kostenlosen Webspace.

    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 :)
  9. 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.
  10. Autor dieses Themas

    fr34qy

    fr34qy hat kostenlosen Webspace.

    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 :thumb: 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&auml;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="&nbsp;&nbsp;'.$fach.'" class="og2">';
    		}
    		
    		if ($fachid_old != $fachid) {
    			if ($schulart_old != $schulart) {
    				echo '</optgroup></optgroup>';
    				echo '<optgroup label="'.$schulart.'" class="og1">';
    				echo '<optgroup label="&nbsp;&nbsp;'.$fach.'" class="og2">';
    			} else {
    				echo '</optgroup>';
    				echo '<optgroup label="&nbsp;&nbsp;'.$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 :)
  11. Diskutiere mit und stelle Fragen: Jetzt kostenlos anmelden!

    lima-city: Gratis werbefreier Webspace für deine eigene Homepage

Dir gefällt dieses Thema?

Über lima-city

Login zum Webhosting ohne Werbung!