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

jensengemann

Benutzer
Beiträge
9
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 ???
 
Werbung:
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.
 
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.
 
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)).
 
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.
 
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 ...
 
Werbung:
Stimmt, eigentlich gibt es noch einen Fall wo ein Zeitraum vollständig im anderen liegt, das müsste man dann noch ergänzen.
 
Zurück
Oben