1. Willkommen im Forum für alle Datenbanken! Registriere Dich kostenlos und diskutiere über DBs wie Mysql, MariaDB, Oracle, Sql-Server, Postgres, Access uvm
    Information ausblenden

benötige Denkanstoß für eine Query - Bereichsabfrage

Dieses Thema im Forum "MySQL und MariaDB" wurde erstellt von jensengemann, 6 November 2018.

  1. jensengemann

    jensengemann Benutzer

    Hallo,
    um in einen Buchungskalender Termine zu hinterlegen ich habe in einer Tabelle zwei Timestamps abgespeichert ("von" und "bis"). Nun möchte ich beim Eintragen eines neuen Termins diese Tabelle abfragen ob sich der Termin ("von" - "bis") mit einem vorhandenen Datensatz überschneidet bzw. ob ein dementsprechender Eintrag existiert.

    ...mir scheint das recht simple, ...aber mir fällt gerade einfach nicht die richtige Formel dafür ein.

    Hat da jemand eine Idee ???
     
  2. akretschmer

    akretschmer Datenbank-Guru

    Ja, da böten sich ganz enorm RANGE-Datentypen an - die aber MySQL nicht hat. Hast Du die Chance, auf PostgreSQL zu wechseln? Da kannst Du z.B. via EXCLUSION CONSTRAINT verhindern, daß sich 2 Termine überschneiden. Z.B. Hotelbuchung:

    Code:
    test=# create table hotel (zimmer int, belegt daterange, exclude using gist(zimmer with =, belegt with &&));
    CREATE TABLE
    test=*# insert into hotel values (1, '[2018-11-01, 2018-11-20)');
    INSERT 0 1
    test=*# insert into hotel values (1, '[2018-11-20, 2018-11-30)');
    INSERT 0 1
    test=*# insert into hotel values (1, '[2018-11-15, 2018-11-25)');
    FEHLER:  kollidierender Schlüsselwert verletzt Exclusion-Constraint »hotel_zimmer_belegt_excl«
    DETAIL:  Schlüssel (zimmer, belegt)=(1, [2018-11-15,2018-11-25)) kollidiert mit vorhandenem Schlüssel (zimmer, belegt)=(1, [2018-11-01,2018-11-20)).
    test=*#
    
    oder prüfen, ob der 16.11. belegt ist:

    Code:
    test=*# select * from hotel where belegt @> '2018-11-16'::date;
     zimmer |         belegt         
    --------+-------------------------
          1 | [2018-11-01,2018-11-20)
    (1 row)
    
    test=*#
    
    
    Da das ganze indexbasiert erfolgt, ist das auch wirklich flott.
     
  3. akretschmer

    akretschmer Datenbank-Guru

    davon abgesehen, man kann in MySQL prüfen, ob es einen solchen Eintrag gibt. Wird ein etwas komplexerer Ausdruck mit den nötigen Vergleichen auf Überlappung. Das dürfte auch von der Performance bei größeren Tabellen mit der Zeit ein Problem werden, von konkurriernden Zugriffen mal gar nicht gesprochen. Als CONSTRAINT, daß sich Zeiträume nicht überlappen dürfen, kannst Du dann aber bei MySQL nur träumen, da fehlt dann wirklich die nötige technische Basis in MySQL.
     
  4. jensengemann

    jensengemann Benutzer

    aha, hab leider zu PostgreSQL gar kein Bezug und auch keine Möglichkeit umzusteigen. Für das was ich vorhabe ist die Performance nicht ganz so ausschlaggebend.

    ich hab das jetzt in MySQL so gelöst:
    Code:
    $checkquery="SELECT id FROM termine WHERE ((von >= '$vonstring' AND von <= '$bisstring') OR (bis >= '$vonstring' AND bis <= '$bisstring')) OR ((von <= '$vonstring' AND bis >= '$vonstring') OR (von <= '$bisstring' AND bis >= '$bisstring')) LIMIT 1";
    eben eine Abfrage für (innerhalb des neuen datensatzes ($vonstring ODER $bisstring)) ODER (den Bereich innerhalb von vorhandenen Datensätzen (von ODER bis)).
     
  5. akretschmer

    akretschmer Datenbank-Guru

    ja, so in der Art. Hab es jetzt nicht geprüft, aber von weitem sieht es passend aus ;-)
     
  6. ukulele

    ukulele Datenbank-Guru

    Etwas einfacher sollte es mit
    Code:
    WHERE '$vonstring' BETWEEN von AND bis OR '$bisstring' BETWEEN von AND bis
    gehen. Ein Index auf von,bis und dad dauert auch nicht so lange.
     
  7. akretschmer

    akretschmer Datenbank-Guru

    wenn $vonstring vor von ist und $bisstring nach bis ist auch?

    Indexe: soweit mir bekannt, kann MySQL in einer Query je Table nur einen Index nutzen. Das mag schon helfen, zieht aber dennoch u.U. viel tablescan nach sich ...
     
  8. Walter

    Walter Administrator Mitarbeiter

    Dein Wissensstand ist schon ein wenig angestaubt :) Mysql macht zB einen Index merge um mehrere Indexe zu nutzen
     
    akretschmer gefällt das.
  9. akretschmer

    akretschmer Datenbank-Guru

    stimmt, seit version 5.
     
  10. ukulele

    ukulele Datenbank-Guru

    Stimmt, eigentlich gibt es noch einen Fall wo ein Zeitraum vollständig im anderen liegt, das müsste man dann noch ergänzen.
     
Die Seite wird geladen...

Diese Seite empfehlen

  1. Diese Seite verwendet Cookies. Wenn du dich weiterhin auf dieser Seite aufhältst, akzeptierst du unseren Einsatz von Cookies.
    Information ausblenden