Yadgar: MySQL: Fallunterscheidung innerhalb eines Queries

Hi(gh)!

Tabelle "kreis", Datenfelder "id", "name", "regierungsbezirk_id" und "bundesland_id". Da es längst nicht in allen Bundesländern Regierungsbezirke als Verwaltungsebene zwischen Kreis und Land gibt, andererseits bei vorhandenen Regierungsbezirken das Bundesland über die Tabelle "regbez" (für die Regierungsbezirke) ermittelt werden kann, darf entweder das Feld "regierungsbezirk_id" oder das Feld "bundesland_id" NULL sein (nicht aber beide zugleich!).

Das Problem ist jetzt: in der Datensatzausgabe (zur Orientierung für mich beim Eingeben, nicht als Endbenutzer-Ausgabe) wird der besseren Übersichtlichkeit halber nicht die aus "regbez" übernommene "id" angezeigt, sondern gleich der Klarname des Regierungsbezirks. Der dazu verwendete Query-String lautet:

SELECT kreis.id, kreis.name, regierungsbezirk_id
     , regbez.name, regbez.id
     , kreis.bundesland_id
     , land.name, land.id
FROM kreis, regbez, land
WHERE kreis.bundesland_id = land.id AND regierungsbezirk_id = regbez.id
LIMIT ".$offset.", ".$range.";

(Edit Rolf B: Query lesbar(er) gemacht)

Wird im Eingabeformular jedoch kein Wert für "regierungsbezirk_id" übermittelt, kann kein Datensatz ausgegeben werden, weil der zweite Teil der WHERE-Bedingung nicht erfüllt ist. Wie bringe ich jetzt dem Query mittels einer IF-Klausel bei, dass bei regierungsbezirk_id = NULL in der Spalte für den Regierungsbezirks-Klarnamen "(keiner)" angezeigt wird?

Bis bald im Khyberspace!

Yadgar

  1. Hallo Yadgar,

    Problem 1 ist, dass Du bei fehlendem Regierungsbezirk überhaupt eine Ausgabezeile bekommst. Problem 2 ist dann, wie Du den fehlenden Regierungsbezirk darstellst.

    Wenn Du in der kreis-Tabelle nämlich eine Regierungsbezirks-ID hast, die in der regbez-Tabelle nicht vorkommt, wirst Du den Kreis mit der von Dir gezeigten Query gar nicht ausgeben. Dein Vorgehen mit einem Schlüsselvergleich im WHERE führt zu einem INNER JOIN, was Du aber brauchst, ist ein LEFT JOIN. Den bekommst Du über WHERE nicht hin, sondern musst die entsprechende SQL Syntax verwenden.

    Die ID-Spalten hattest Du sicherlich nur zum Debugging drin, die lasse ich mal weg.

    SELECT kreis.id, kreis.name, regbez.name, land.name
    FROM kreis
         JOIN land ON kreis.bundesland_id = land.id
         LEFT JOIN regbez ON kreis.regierungsbezirk_id = regbez.id 
    LIMIT ".$offset.", ".$range.";
    

    "JOIN land" ist ein inner join, "LEFT JOIN regbez" ist ein left outer join. Was das genau ist, verrät Dir das SQL Handbuch.

    Nun bekommst Du in den Zeilen, wo keine regierungsbezirk_id vorliegt, den Wert NULL in der regbez.name Spalte. Du kannst das im SQL fixen, aber eigentlich ist das nichts, was in die DB Zugriffsschicht gehört. Das solltest Du eigentlich im PHP tun.

    Aber wenn Du es unbedingt im SQL machen willst, dann hat MySQL da mehrere Funktionen im Angebot.

    Am einfachsten ist wohl hier IFNULL:

    SELECT kreis.id, kreis.name, IFNULL(regbez.name, '(keiner)'), land.name
    FROM kreis
         JOIN land ON kreis.bundesland_id = land.id
         LEFT JOIN regbez ON kreis.regierungsbezirk_id = regbez.id 
    LIMIT ".$offset.", ".$range.";
    

    Rolf

    --
    sumpsi - posui - clusi