klaus: (MySQL) überschneidende Einträge filtern?

Hallo,

ich habe einen Urlaubsplaner für die Mitarbeiter. In einer Tabelle stehen die Abwesenheiten, in einer Tabelle steht die Abwesenheitsarten (z.B. auch Schulung, Geschäftsreise, ...) mit den entsprechenden Farben und in einer Tabelle die Feiertage.

Diese möchte ich nun kombiniert anzeigen lassen.
Ich möchte nun aber diejenigen Feiertage aus der Ergebnisliste filtern, die in einen Urlaubseintrag fallen würden.
Nur wie könnte ich das bewerkstelligen?
Habt ihr vielleicht eine Idee?

Meine bisherige Abfrage sieht also wie folgt aus:

select
   a.idnr,a.bestaetigt,a.urlaubvon,a.urlaubbis,
   a.halbertag,c.bezeichnung,c.farbe
from urlaubdaten as a left join urlaubarten as c on a.artnr = c.artnr

where a.personalnummer='$personalnummer' AND a.urlaubvon like '$zeitraum-%' AND a.geloescht <> 'J'

UNION select
   '','J',feiertag AS urlaubvon,feiertag AS urlaubbis,'',
   feiertag_text AS bezeichnung,'gelb'
from feiertage

where feiertag like '2007%' order by urlaubvon

  1. yo,

    warum der LEFT JOIN in der ersten abfrage, gibt es den abwesenheiten in der tabelle urlaubsdaten die keinen entsprechenden eintrag für die urlaubsart haben ?

    was dein problem angeht, mach einen JOIN der drei tabellen und als JOIN bedingung nimmst du du das datum des feiertages und schauchst mit dem BETWEEN Operator, ob dieser in einem urlaub fällt.

    SELECT ...
    FROM urlaubdaten a
    INNER JOIN feiertage f ON f.feiertag BETWEEN a.urlaubvon AND a.urlaubbis
    INNER (LEFT) JOIN urlaubarten c ON a.artnr = c.artnr

    Ilja

    1. Hallo Ilja,

      vielen Dank für Deine schnelle Antwort. Ich bin aber gerade erst zurück an meinen PC.

      was dein problem angeht, mach einen JOIN der drei tabellen und als JOIN bedingung nimmst du du das datum des feiertages und schauchst mit dem BETWEEN Operator, ob dieser in einem urlaub fällt.

      SELECT ...
      FROM urlaubdaten a
      INNER JOIN feiertage f ON f.feiertag BETWEEN a.urlaubvon AND a.urlaubbis
      INNER (LEFT) JOIN urlaubarten c ON a.artnr = c.artnr

      Wenn ich Deine Abfrage ausprobiere, erhalte ich lediglich den Eintrag zurück, der sich mit einem Feiertag überschneidet. Ich möchte aber doch genau die andere Menge, alle, wo sich kein Feiertag überschneidet.

      1. Hi

        Wenn ich Deine Abfrage ausprobiere, erhalte ich lediglich den Eintrag zurück, der sich mit einem Feiertag überschneidet. Ich möchte aber doch genau die andere Menge, alle, wo sich kein Feiertag überschneidet.

        Dann (Tipp ins Dunkelgrüne) benutzt du einen FULL OUTER JOIN und prüfst beide Seiten (geeignete Spalten beider ge-jointen Tabellen) auf NULL.

        Ciao, Frank

        1. Hallo Frank,

          Dann (Tipp ins Dunkelgrüne) benutzt du einen FULL OUTER JOIN und prüfst beide Seiten (geeignete Spalten beider ge-jointen Tabellen) auf NULL.

          Wenn ich INNER JOIN durch ein OUTER JOIN ersetze, schmeisst's mir einen SQL-Fehler raus.

          Wenn ich statt dem BETWEEN ein NOT BETWEEN schreibe, erhalte ich dummerweise auch alle die Einträge, die nicht der Personalnummer und nicht dem Datumsbereich betreffen.

          Vielleicht kannst Du (grob) skizzieren, wie der select aussieht, kann auch sein, dass ich Dir einfach nicht folgen konnte.

          1. wie wäre es mit deinem konkreten SQL, was du jetzt gebaut hast und der konkreten Fehlermeldung, die es dir schmeisst?

            Frank

      2. yo,

        Ich möchte aber doch genau die andere Menge, alle, wo sich kein Feiertag überschneidet.

        ok, dann habe ich das mit dem filtern falsch aufgefasst, ich dachte, genau diese wolltest du haben. Hier also der andere fall:

        SELECT ...
        FROM urlaubdaten a
        INNER (LEFT) JOIN urlaubarten c ON a.artnr = c.artnr
        WHERE NOT EXISTS (SELECT NULL
                          FROM feiertage f
                          WHERE f.feiertag BETWEEN a.urlaubvon AND
        a.urlaubbis
                         )
        ;

        Ilja

        1. Hallo Ilja,

          SELECT ...
          FROM urlaubdaten a
          INNER (LEFT) JOIN urlaubarten c ON a.artnr = c.artnr
          WHERE NOT EXISTS (SELECT NULL
                            FROM feiertage f
                            WHERE f.feiertag BETWEEN a.urlaubvon AND
          a.urlaubbis
                           )
          ;

          Das hab ich jetzt mal daraus gebastelt.
          Sieht fast gut aus, aber jetzt wird auch der Urlaub, in den ein Feiertag fällt, herausgefiltert. Ich möchte ja nur den Feiertag, sofern in eine Urlaubszeit fällt, herausgenommen haben.

          SELECT a.idnr, a.bestaetigt, a.urlaubvon, a.urlaubbis, a.halbertag, c.bezeichnung, c.farbe
          FROM urlaubdaten a
          INNER JOIN urlaubarten c ON a.artnr = c.artnr
          WHERE a.personalnummer = '3122'
          AND a.urlaubvon LIKE '2007-%'
          AND a.geloescht <> 'J'
          AND NOT
          EXISTS (SELECT NULL
          FROM feiertage f
          WHERE f.feiertag
          BETWEEN a.urlaubvon
          AND a.urlaubbis)
          ORDER BY urlaubvon

          1. yo,

            schwere geburt und mir ist noch nicht ganz klar, was du willst. du willst nur die feiertage anzeigen lassen, welche nicht in einem urlaub liegen ?

            dann musst du das ganze enfach umdrehen, nämlich die äußere abfrage nach innen und die inner unterabfrage nach aussen und wieder mit dem NOT EXISTS verbinden.

            wenn das immer noch nicht das ist was du wills,t solltest du am besten mal beispiele mit daten ausgeben, welche ausgangsdaten hast du, welche willst du ausgeben lassen.

            Ilja

            1. Hallo Ilja,

              ich glaube, ich habe es (dank Deiner Hilfe) selber hinbekommen.
              Meine letzter Stand der Abfrage sieht jetzt wie folgt aus:

              Sieht zwar reichlich komplex aus, aber besser habe ich es (bisher) nicht gelöst bekommen.

              SELECT a.idnr, a.bestaetigt, a.urlaubvon, a.urlaubbis, a.halbertag, c.bezeichnung, c.farbe
              FROM urlaubdaten AS a
              LEFT JOIN urlaubarten AS c ON a.artnr = c.artnr
              WHERE a.personalnummer = '3122'
              AND a.urlaubvon LIKE '2007-%'
              AND a.geloescht <> 'J'
              UNION SELECT '', 'J', f.feiertag AS urlaubvon, f.feiertag AS urlaubbis, '', f.feiertag_text AS bezeichnung, 'gelb'
              FROM feiertage f
              WHERE f.feiertag LIKE '2007-%'
              AND NOT
              EXISTS (

              SELECT g.idnr
              FROM urlaubdaten g
              WHERE g.personalnummer = '3122'
              AND g.urlaubvon LIKE '2007-%'
              AND g.geloescht <> 'J'
              AND f.feiertag
              BETWEEN g.urlaubvon
              AND g.urlaubbis
              )
              ORDER BY urlaubvon