Knud: (MySQL) Abfrage-Problem

Hallo,

ich habe die folgende Abfrage definiert:

SELECT a. * , b.vorname, b.name, b.verantwortlich, c.bezeichnung, c.farbe
FROM (
mitarbeiter AS b
LEFT JOIN urlaubdaten AS a ON a.personalnummer = b.personalnummer
)
LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
WHERE (
a.urlaubvon
LIKE '2004-%' OR a.urlaubbis
LIKE '2004-%'
) AND b.firma = 'Firma GmbH' AND b.abteilung = 'Einkauf'
ORDER BY a.personalnummer, a.urlaubvon

Diese Abfrage liefert mir leider nur diejenigen Mitarbeiter, die auch einen Eintrag in der Tabelle urlaubsdaten haben.
Wie stelle ich nun die Abfrage um, dass ich alle Mitarbeiter einer Abteilung und Firma bekomme, unabhängig davon, ob ein Eintrag existiert?

Leider funktioniert das (+) nur bei Oracle. Und ich habs leider nicht hinbekommen, die Abfrage so umzustellen, dass ein
where a.personalnummer is NULL
miteingebaut werden kann.

Wäre dankbar für nen Tipp,

Gruß,

Knud

  1. yo,

    Leider funktioniert das (+) nur bei Oracle.

    das (+) ist nichts anderes als ein outer join, nur halt eine andere syntax.

    lass doch mal die klammern um den ersten join weg.

    Ilja

    1. yo,

      Leider funktioniert das (+) nur bei Oracle.

      das (+) ist nichts anderes als ein outer join, nur halt eine andere syntax.

      lass doch mal die klammern um den ersten join weg.

      Ilja

      Hmm, verstehe ich nicht ganz.
      Was meinst Du mit outer join?
      Wenn ich die Join Syntax weglasse und den select etwa so ausbaue:

      select a.*,b.*,c* from telefon b,urlaubdaten a,urlaubarten,c where...

      ...kommt dasselbe raus. Nur die Sätze, die auch in a _und_ b sind.

      Gruß,

      Knud

      1. yo,

        nicht die gesamte join syntax weglassen, sondern nur die klammern darum.

        Ilja

        1. yo,

          nicht die gesamte join syntax weglassen, sondern nur die klammern darum.

          Ilja

          Auch wenn ich _nur_ die Klammern weglasse, erhalte ich dasselbe Ergebnis:
          Nur der eine Satz der auch in urlaubdaten existiert, wird angezeigt.

          Gruß,

          Knud

          1. yo,

            ich kann den fehler im moment auch nicht erkennen, LEFT JOIN sollte ja eigentliche alle mitarbeiter auflisten. es gibt aber einenw eg, um sich den problem anzunähern. anstelle gleiche alle beiden JOINS auszuführen. versuch doch erst mal nur den ersten, um zu sehen, ob da noch alle mitarbeiter mit an board sind.

            Ilja

            1. Hallo,

              ich kann den fehler im moment auch nicht erkennen, LEFT JOIN sollte ja eigentliche alle mitarbeiter auflisten.

              Tut es auch. Nur dann sagt er doch in der WHERE-Klausel, dass er nur die Datensätze will, bei denen die Daten in Feldern der Tabelle urlaubdaten bestimmte Anforderungen erfüllen. Damit schließt er alle Datensätze aus, bei denen die Felder der Tabelle urlaubdaten NULL enthalten. Das sind aber genau die Datensätze, die durch das LEFT JOIN zusätzlich, im Gegensatz zum INNER JOIN, hinzugekommen sind.

              viele Grüße

              Axel

              1. yo,

                das sehe ich anders, leztlich werden in der where klausel nur datensätze der einzelnen tabellen gefiltert, bevor der left join ausgeführt wird. die rechte tabelle des left joins könnte praktisch leer sein und er sollte immer noch alle datensätze der linken tabllen anzeigen.

                Ilja

                1. Hallo,

                  das sehe ich anders, leztlich werden in der where klausel nur datensätze der einzelnen tabellen gefiltert, bevor der left join ausgeführt wird. die rechte tabelle des left joins könnte praktisch leer sein und er sollte immer noch alle datensätze der linken tabllen anzeigen.

                  Nein. Die allgemeine Syntax ist:
                  SELECT Feldliste FROM Tabellenausdruck WHERE Kriterien
                  wobei:
                  Tabellenausdruck:= Ein Ausdruck, der eine oder mehrere Tabellen kennzeichnet, aus denen Daten abgerufen werden. Der Ausdruck kann ein einzelner Tabellenname sein, ein Name einer gespeicherten Abfrage oder ein zusammengesetzter Name, der sich aus einer Verknüpfung (INNER JOIN, LEFT JOIN oder RIGHT JOIN) ergibt.
                  Kriterien:= Ein Ausdruck mit Kriterien, die Datensätze erfüllen müssen, damit sie in das Abfrageergebnis aufgenommen werden.

                  Mit "Datensätze" sind dabei die Datensätze gemeint, welche aus dem Tabellenausdruck hervorgehen. Im Tabellenausdruck kann es eine WHERE-Klausel nur dann geben, wenn es sich dort um Unterabfragen handelt.

                  So könnte, meiner Meinung nach, die Lösung des Problems aussehen:

                  SELECT a.*, b.vorname, b.name, b.verantwortlich, c.bezeichnung, c.farbe
                  FROM
                  (mitarbeiter AS b LEFT JOIN urlaubdaten AS a ON a.personalnummer = b.personalnummer) LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
                  WHERE (a.urlaubvon LIKE '2004-%' OR a.urlaubbis LIKE '2004-%' OR (a.urlaubvon IS NULL AND a.urlaubbis IS NULL))
                  AND b.firma = 'Firma GmbH' AND b.abteilung = 'Einkauf'
                  ORDER BY a.personalnummer, a.urlaubvon

                  viele Grüße

                  Axel

                  1. yo,

                    bei mir werden erst alle where kritereien ausgeführt und dann der/die join/s gebildet. und wnen ich deine syntax richtig interpretiere, dann sagt sie genau das auch aus. was natürlich sien kann ist, dass alle mitarbeiter dieser firma und abteilung schon zufälling einen urlaubsplan haben. aber davon gehe ich mal nicht aus.

                    wie gesagt, mein tip wäre immer noch, mal erst einmal einen join durchzuführen und auch die where kriterien nacheinander reinzunehmen, um zu sehen, zu wlechen ergebnissen das führt. das bringt einem machmal auf die richtige spur.

                    Ilja

  2. Hallo,

    ich habe die folgende Abfrage definiert:

    SELECT a. * , b.vorname, b.name, b.verantwortlich, c.bezeichnung, c.farbe

    ^Diese Lücke ist hier falsch.

    FROM (
    mitarbeiter AS b
    LEFT JOIN urlaubdaten AS a ON a.personalnummer = b.personalnummer
    )
    LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
    WHERE (
    a.urlaubvon
    LIKE '2004-%' OR a.urlaubbis
    LIKE '2004-%'
    ) AND b.firma = 'Firma GmbH' AND b.abteilung = 'Einkauf'
    ORDER BY a.personalnummer, a.urlaubvon

    Diese Abfrage liefert mir leider nur diejenigen Mitarbeiter, die auch einen Eintrag in der Tabelle urlaubsdaten haben.

    Das ist logisch. Bei Dir hat die Tabelle "urlaubdaten" den Alias a und Du willst doch ausdrücklich _nur_ Datensätze, bei denen gilt:

    a.urlaubvon LIKE '2004-%' OR a.urlaubbis LIKE '2004-%'

    Bei Datensätzen, die Werte in mitarbeiter, aber _keine_ Werte in urlaubdaten haban, haben diese Felder _beide_ den Wert NULL.

    viele Grüße

    Axel

    1. Hallo,

      Diese Abfrage liefert mir leider nur diejenigen Mitarbeiter, die auch einen Eintrag in der Tabelle urlaubsdaten haben.
      Das ist logisch. Bei Dir hat die Tabelle "urlaubdaten" den Alias a und Du willst doch ausdrücklich _nur_ Datensätze, bei denen gilt:

      a.urlaubvon LIKE '2004-%' OR a.urlaubbis LIKE '2004-%'

      Bei Datensätzen, die Werte in mitarbeiter, aber _keine_ Werte in urlaubdaten haban, haben diese Felder _beide_ den Wert NULL.

      viele Grüße

      Axel

      Aber auch wenn ich die Abfrage dann so formuliere...

      SELECT a. * , b.vorname, b.name, b.verantwortlich, c.bezeichnung, c.farbe
      FROM (
      urlaubdaten AS a
      LEFT JOIN telefon AS b ON a.personalnummer = b.personalnummer
      )
      LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
      WHERE (
      a.personalnummer IS NULL OR (
      a.urlaubvon
      LIKE '2004-%' OR a.urlaubbis
      LIKE '2004-%'
      )
      ) AND b.firma = 'Firma GmbH' AND b.abteilung = 'Einkauf'
      ORDER BY a.personalnummer, a.urlaubvon

      ... erscheint bei mir nur der einer Satz, der in Urlaubdaten vorhanden ist.

      Gruß,

      Knud

      1. Hallo,

        Aber auch wenn ich die Abfrage dann so formuliere...

        SELECT a. * , b.vorname, b.name, b.verantwortlich, c.bezeichnung, c.farbe

        ^Diese Lücke ist immer noch falsch.

        FROM (
        urlaubdaten AS a

        ^Aus dieser Tabelle werden alle Datensätze genommen.

        LEFT JOIN telefon AS b ON a.personalnummer = b.personalnummer

        ^Was ist plötzlich telefon? Wo sind die Mitarbeiter geblieben?

        )
        LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
        WHERE (
        a.personalnummer IS NULL OR (

        ^Das wird wahrscheinlich nie zutreffen, weil aus a ohnehin alle Datensätze genommen werden.

        a.urlaubvon
        LIKE '2004-%' OR a.urlaubbis
        LIKE '2004-%'
        )
        ) AND b.firma = 'Firma GmbH' AND b.abteilung = 'Einkauf'
        ORDER BY a.personalnummer, a.urlaubvon

        ... erscheint bei mir nur der einer Satz, der in Urlaubdaten vorhanden ist.

        Das ist wieder logisch, weil die Tabelle urlaubarten im LEFT JOIN ganz links steht.

        Vergleichst Du mal bitte diese Abfrage mit der von Dir im Ausgangsposting vorgestellten:

        SELECT a. * , b.vorname, b.name, b.verantwortlich, c.bezeichnung, c.farbe
        FROM (
        mitarbeiter AS b
        LEFT JOIN urlaubdaten AS a ON a.personalnummer = b.personalnummer
        )
        LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
        WHERE (
        a.urlaubvon
        LIKE '2004-%' OR a.urlaubbis
        LIKE '2004-%'
        ) AND b.firma = 'Firma GmbH' AND b.abteilung = 'Einkauf'
        ORDER BY a.personalnummer, a.urlaubvon

        und sagst mir dann, ob Du mich veralbern willst?

        viele Grüße

        Axel